Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/debugtools/DDR_VM/binary_operation_investigation/generate_test_suite.pl
6000 views
1
#!/usr/bin/perl
2
3
# Copyright (c) 2009, 2017 IBM Corp. and others
4
#
5
# This program and the accompanying materials are made available under
6
# the terms of the Eclipse Public License 2.0 which accompanies this
7
# distribution and is available at https://www.eclipse.org/legal/epl-2.0/
8
# or the Apache License, Version 2.0 which accompanies this distribution and
9
# is available at https://www.apache.org/licenses/LICENSE-2.0.
10
#
11
# This Source Code may also be made available under the following
12
# Secondary Licenses when the conditions for such availability set
13
# forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
14
# General Public License, version 2 with the GNU Classpath
15
# Exception [1] and GNU General Public License, version 2 with the
16
# OpenJDK Assembly Exception [2].
17
#
18
# [1] https://www.gnu.org/software/classpath/license.html
19
# [2] http://openjdk.java.net/legal/assembly-exception.html
20
#
21
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
22
23
# Script to build a C testcase for generating test cases for scalar types
24
25
# Usage: perl generate_test_suite.pl <name of cpp file to generate>
26
27
# Andrew Hall
28
29
use strict;
30
use warnings;
31
32
my $output_file = shift;
33
34
die "You didn't specify an output file" unless defined $output_file;
35
36
open(my $out,'>',$output_file) or die "Couldn't open $output_file: $!";
37
38
#Operations to generate data for
39
my @ops = ({op=>'add',operator=>'+'}, {op=>'sub',operator=>'-'});
40
41
my @bitwise_ops = ({op=>'bitAnd',operator=>'&'}, {op=>'bitOr',operator=>'|'});
42
43
#Types to generate data for
44
my @types = qw{U_8 U_16 U_32 U_64 I_8 I_16 I_32 I_64 UDATA IDATA};
45
46
#Conversion table. Equivalent of the HTML table produced by the prettify script
47
#Tells us what format to expect all the output in
48
my %type_conversion_table = (U_8 => {U_8=>'U_8',
49
U_16=>'I_32',
50
U_32=>'U_32',
51
U_64=>'U_64',
52
I_8=>'I_32',
53
I_16=>'I_32',
54
I_32=>'I_32',
55
I_64=>'I_64',
56
UDATA=>'UDATA',
57
IDATA=>'IDATA'
58
},
59
60
U_16=>{U_8=>'I_32',
61
U_16=>'U_16',
62
U_32=>'U_32',
63
U_64=>'U_64',
64
I_8=>'I_32',
65
I_16=>'I_32',
66
I_32=>'I_32',
67
I_64=>'I_64',
68
UDATA=>'UDATA',
69
IDATA=>'IDATA'
70
},
71
72
U_32=>{U_8=>'U_32',
73
U_16=>'U_32',
74
U_32=>'U_32',
75
U_64=>'U_64',
76
I_8=>'U_32',
77
I_16=>'U_32',
78
I_32=>'U_32',
79
I_64=>'I_64',
80
UDATA=>'UDATA',
81
IDATA=>'IDATA'
82
},
83
84
U_64=>{U_8=>'U_64',
85
U_16=>'U_64',
86
U_32=>'U_64',
87
U_64=>'U_64',
88
I_8=>'U_64',
89
I_16=>'U_64',
90
I_32=>'U_64',
91
I_64=>'U_64',
92
UDATA=>'U_64',
93
IDATA=>'ERROR'
94
},
95
96
I_8=>{U_8=>'I_32',
97
U_16=>'I_32',
98
U_32=>'U_32',
99
U_64=>'U_64',
100
I_8=>'I_32',
101
I_16=>'I_32',
102
I_32=>'I_32',
103
I_64=>'I_64',
104
UDATA=>'UDATA',
105
IDATA=>'IDATA'
106
},
107
108
I_16=>{U_8=>'I_32',
109
U_16=>'I_32',
110
U_32=>'U_32',
111
U_64=>'U_64',
112
I_8=>'I_32',
113
I_16=>'I_16',
114
I_32=>'I_32',
115
I_64=>'I_64',
116
UDATA=>'UDATA',
117
IDATA=>'IDATA'
118
},
119
120
I_32=>{U_8=>'I_32',
121
U_16=>'I_32',
122
U_32=>'U_32',
123
U_64=>'U_64',
124
I_8=>'I_32',
125
I_16=>'I_32',
126
I_32=>'I_32',
127
I_64=>'I_64',
128
UDATA=>'UDATA',
129
IDATA=>'IDATA'
130
},
131
132
I_64=>{U_8=>'I_64',
133
U_16=>'I_64',
134
U_32=>'I_64',
135
U_64=>'U_64',
136
I_8=>'I_64',
137
I_16=>'I_64',
138
I_32=>'I_64',
139
I_64=>'I_64',
140
UDATA=>'ERROR',
141
IDATA=>'I_64'
142
},
143
144
UDATA=>{U_8=>'UDATA',
145
U_16=>'UDATA',
146
U_32=>'UDATA',
147
U_64=>'U_64',
148
I_8=>'UDATA',
149
I_16=>'UDATA',
150
I_32=>'UDATA',
151
I_64=>'ERROR',
152
UDATA=>'UDATA',
153
IDATA=>'UDATA'
154
},
155
156
IDATA=>{U_8=>'IDATA',
157
U_16=>'IDATA',
158
U_32=>'IDATA',
159
U_64=>'ERROR',
160
I_8=>'IDATA',
161
I_16=>'IDATA',
162
I_32=>'IDATA',
163
I_64=>'I_64',
164
UDATA=>'UDATA',
165
IDATA=>'IDATA'
166
},);
167
168
#List of generated functions (called by main at the end)
169
my @function_list;
170
171
generate_file_header();
172
173
generate_arithmetic_functions();
174
175
generate_bitwise_functions();
176
177
generate_equals_functions();
178
179
generate_main_function();
180
181
close($out);
182
183
exit;
184
185
sub generate_bitwise_functions
186
{
187
foreach my $type (@types) {
188
189
foreach my $operation (@bitwise_ops) {
190
my $op_name = $operation->{op};
191
my $operator = $operation->{operator};
192
my $function_name = "test${op_name}${type}";
193
push @function_list, $function_name;
194
195
generate_type_function_header ($out,$function_name);
196
my $base_var = generate_locals ($out,$type);
197
generate_post_local_header($out,$type,$op_name);
198
199
foreach my $second_arg_type (@types) {
200
201
print $out <<END;
202
203
cout << "SUBSECTION $type WITH $second_arg_type" << endl;
204
END
205
206
my $var_1 = $base_var;
207
my $var_2 = lc $second_arg_type;
208
my $expected_type = $type_conversion_table{$type}->{$second_arg_type};
209
die "No expected type for $type, $second_arg_type" unless defined $expected_type;
210
211
if ($expected_type eq 'ERROR') {
212
print $out <<END;
213
214
cout << "INVALID: $type,$op_name,$second_arg_type" << endl;
215
216
END
217
next;
218
}
219
220
my $bitpattern1a = get_pattern_1a($type);
221
my $bitpattern1b = get_pattern_1b($second_arg_type);
222
223
#Test max+1
224
print $out <<END;
225
$var_1 = $bitpattern1a;
226
$var_2 = $bitpattern1b;
227
END
228
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
229
230
my $bitpattern2a = get_pattern_2a($type);
231
my $bitpattern2b = get_pattern_2b($second_arg_type);
232
233
#Test max+1
234
print $out <<END;
235
$var_1 = $bitpattern2a;
236
$var_2 = $bitpattern2b;
237
END
238
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
239
}
240
241
generate_type_function_footer($out);
242
}
243
}
244
}
245
246
sub generate_equals_functions
247
{
248
foreach my $type (@types) {
249
250
my $op_name = "equals";
251
my $operator = "==";
252
my $function_name = "test${op_name}${type}";
253
push @function_list, $function_name;
254
255
generate_type_function_header ($out,$function_name);
256
my $base_var = generate_locals ($out,$type);
257
generate_post_local_header($out,$type,$op_name);
258
259
foreach my $second_arg_type (@types) {
260
print $out <<END;
261
cout << "SUBSECTION $type WITH $second_arg_type" << endl;
262
END
263
264
my $var_1 = $base_var;
265
my $var_2 = lc $second_arg_type;
266
my $expected_type = $type_conversion_table{$type}->{$second_arg_type};
267
die "No expected type for $type, $second_arg_type" unless defined $expected_type;
268
269
if ($expected_type eq 'ERROR') {
270
print $out <<END;
271
272
cout << "INVALID: $type,$op_name,$second_arg_type" << endl;
273
274
END
275
next;
276
}
277
278
$expected_type = 'bool';
279
280
#Test 0=0
281
print $out <<END;
282
$var_1 = 0;
283
$var_2 = 0;
284
END
285
286
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
287
288
if ( isSigned($type) && isSigned($second_arg_type) ) {
289
#Try min, max and -1
290
291
print $out <<END;
292
$var_1 = -1;
293
$var_2 = -1;
294
END
295
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
296
297
my $min = (getWidth($type) > getWidth($second_arg_type)) ? getMin($second_arg_type) : getMin($type);
298
my $max = (getWidth($type) > getWidth($second_arg_type)) ? getMax($second_arg_type) : getMax($type);
299
300
print $out <<END;
301
$var_1 = $min;
302
$var_2 = $min;
303
END
304
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
305
306
print $out <<END;
307
$var_1 = $min - 1;
308
$var_2 = $min - 1;
309
END
310
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
311
312
print $out <<END;
313
$var_1 = $max;
314
$var_2 = $max;
315
END
316
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
317
318
print $out <<END;
319
$var_1 = $max + 1;
320
$var_2 = $max + 1;
321
END
322
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
323
324
} elsif ( !isSigned($type) && isSigned($second_arg_type) ) {
325
#Test -1 vs. MAX
326
my $max = getMax($type);
327
328
print $out <<END;
329
$var_1 = $max;
330
$var_2 = -1;
331
END
332
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
333
334
print $out <<END;
335
$var_1 = $max + 1;
336
$var_2 = -1;
337
END
338
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
339
340
} elsif ( isSigned($type) && !isSigned($second_arg_type) ) {
341
#Test -1 vs. MAX
342
my $max = getMax($second_arg_type);
343
344
print $out <<END;
345
$var_1 = -1;
346
$var_2 = $max;
347
END
348
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
349
350
print $out <<END;
351
$var_1 = -1;
352
$var_2 = $max + 1;
353
END
354
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
355
356
} else {
357
my $min = (getWidth($type) > getWidth($second_arg_type)) ? getMin($second_arg_type) : getMin($type);
358
my $max = (getWidth($type) > getWidth($second_arg_type)) ? getMax($second_arg_type) : getMax($type);
359
360
print $out <<END;
361
$var_1 = $max;
362
$var_2 = $max;
363
END
364
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
365
366
print $out <<END;
367
$var_1 = $max + 1;
368
$var_2 = $max + 1;
369
END
370
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
371
372
}
373
374
#Generate some bit patterns to trigger funny sign extensions etc.
375
my $bit_pattern1 = (getWidth($type) > getWidth($second_arg_type)) ? get_pattern_1a($second_arg_type) : get_pattern_1a($type);
376
my $bit_pattern2 = (getWidth($type) > getWidth($second_arg_type)) ? get_pattern_1b($second_arg_type) : get_pattern_1b($type);
377
my $bit_pattern3 = (getWidth($type) > getWidth($second_arg_type)) ? get_pattern_2a($second_arg_type) : get_pattern_2a($type);
378
my $bit_pattern4 = (getWidth($type) > getWidth($second_arg_type)) ? get_pattern_2b($second_arg_type) : get_pattern_2b($type);
379
380
print $out <<END;
381
$var_1 = $bit_pattern1;
382
$var_2 = $bit_pattern1;
383
END
384
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
385
386
print $out <<END;
387
$var_1 = $bit_pattern2;
388
$var_2 = $bit_pattern2;
389
END
390
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
391
392
print $out <<END;
393
$var_1 = $bit_pattern3;
394
$var_2 = $bit_pattern3;
395
END
396
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
397
398
print $out <<END;
399
$var_1 = $bit_pattern4;
400
$var_2 = $bit_pattern4;
401
END
402
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
403
404
}
405
generate_type_function_footer($out);
406
}
407
}
408
409
410
sub get_pattern_1a
411
{
412
my $type = shift;
413
414
my $width = getWidth($type);
415
416
$width /= 8;
417
418
return '0x'.('AA'x$width);
419
}
420
421
sub get_pattern_1b
422
{
423
my $type = shift;
424
425
my $width = getWidth($type);
426
427
$width /= 8;
428
429
return '0x'.('55'x$width);
430
}
431
432
sub get_pattern_2a
433
{
434
my $type = shift;
435
return get_pattern_1a($type);
436
}
437
438
sub get_pattern_2b
439
{
440
my $type = shift;
441
442
my $width = getWidth($type);
443
444
$width /= 8;
445
446
return '0x'.('A5'x$width);
447
}
448
449
sub generate_arithmetic_functions
450
{
451
foreach my $type (@types) {
452
453
foreach my $operation (@ops) {
454
my $op_name = $operation->{op};
455
my $operator = $operation->{operator};
456
my $function_name = "test${op_name}${type}";
457
push @function_list, $function_name;
458
459
generate_type_function_header ($out,$function_name);
460
my $base_var = generate_locals ($out,$type);
461
generate_post_local_header($out,$type,$op_name);
462
463
foreach my $second_arg_type (@types) {
464
465
print $out <<END;
466
467
cout << "SUBSECTION $type WITH $second_arg_type" << endl;
468
END
469
470
#Generate 0 + 1 and 0 + 2 operations
471
my $var_1 = $base_var;
472
my $var_2 = lc $second_arg_type;
473
my $expected_type = $type_conversion_table{$type}->{$second_arg_type};
474
die "No expected type for $type, $second_arg_type" unless defined $expected_type;
475
476
if ($expected_type eq 'ERROR') {
477
print $out <<END;
478
479
cout << "INVALID: $type,$op_name,$second_arg_type" << endl;
480
481
END
482
next;
483
}
484
485
#Test 0+0
486
print $out <<END;
487
$var_1 = 0;
488
$var_2 = 0;
489
END
490
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
491
492
#Test 0+1
493
494
print $out <<END;
495
$var_1 = 0;
496
$var_2 = 1;
497
END
498
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
499
500
#Test 0+2
501
print $out <<END;
502
$var_1 = 0;
503
$var_2 = 2;
504
END
505
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
506
507
#For signed secondary types, try 0 + -1
508
509
if (isSigned($second_arg_type)) {
510
print $out <<END;
511
$var_1 = 0;
512
$var_2 = -1;
513
END
514
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
515
}
516
517
my $min = getMin($type);
518
my $max = getMax($type);
519
520
if ($min ne '0') {
521
#Test min+1
522
print $out <<END;
523
$var_1 = $min;
524
$var_2 = 1;
525
END
526
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
527
528
if (isSigned($second_arg_type)) {
529
#Test min-1
530
print $out <<END;
531
$var_1 = $min;
532
$var_2 = -1;
533
END
534
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
535
}
536
}
537
538
539
#Test max+1
540
print $out <<END;
541
$var_1 = $max;
542
$var_2 = 1;
543
END
544
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
545
546
if (isSigned($second_arg_type)) {
547
#Test max-1
548
print $out <<END;
549
$var_1 = $max;
550
$var_2 = -1;
551
END
552
write_testcase_output_line($out,$type,$var_1,$second_arg_type,$var_2,$expected_type,$op_name,$operator);
553
}
554
555
}
556
557
generate_type_function_footer($out);
558
}
559
}
560
}
561
562
sub isSigned
563
{
564
my $type = shift;
565
566
my $firstChar = substr($type,0,1);
567
568
return (lc $firstChar) eq 'i';
569
}
570
571
sub getWidth
572
{
573
my $type = shift;
574
575
if ($type =~ /[UI]_(\d+)/) {
576
return $1;
577
} elsif (substr($type,1,4) eq 'DATA') {
578
#TODO THINK ABOUT TREATING UDATA AS 32 BIT
579
return 32;
580
} else {
581
die "Unknown type $type";
582
}
583
}
584
585
sub getMax
586
{
587
my $type = shift;
588
589
if (isSigned($type)) {
590
my $width = getWidth($type);
591
592
$width /= 8;
593
594
return "0x7f".('ff'x($width-1));
595
} else {
596
my $width = getWidth($type);
597
return "0x".('ff'x($width/8));
598
}
599
}
600
601
sub getMin
602
{
603
my $type = shift;
604
605
if (isSigned($type)) {
606
my $width = getWidth($type);
607
608
$width /= 8;
609
610
return "0x80".('00'x($width-1));
611
} else {
612
return "0";
613
}
614
}
615
616
sub protect_chars
617
{
618
my ($type,$var) = @_;
619
620
if ($type eq 'U_8') {
621
return "(unsigned int)$var";
622
} elsif ($type eq 'I_8') {
623
return "(int)$var";
624
} else {
625
return $var;
626
}
627
}
628
629
sub write_testcase_output_line
630
{
631
my ($out,$type_1,$var_1,$type_2,$var_2,$expected_type,$op_name,$operator) = @_;
632
633
# When printing the values for chars, they have to be converted to a numeric type so they will print as integers
634
my $print_var_1 = protect_chars($type_1,$var_1);
635
my $print_var_2 = protect_chars($type_2,$var_2);
636
my $print_result1 = protect_chars($expected_type,"result1");
637
my $print_result2 = protect_chars($expected_type,"result2");
638
639
print $out <<"END";
640
{
641
$expected_type result1 = $var_1 $operator $var_2;
642
$expected_type result2 = $var_2 $operator $var_1;
643
cout << "$type_1," << hex << $print_var_1 << ",$op_name,$type_2," << hex << $print_var_2 << ",$expected_type," << hex << $print_result1 << "," << hex << $print_result2 << endl;
644
}
645
END
646
}
647
648
sub generate_locals {
649
my $out = shift;
650
my $type = shift;
651
652
print $out <<END;
653
$type base;
654
END
655
656
#Generate an automatic variable for each type
657
foreach my $local_type (@types) {
658
my $var_name = lc $local_type;
659
print $out <<END;
660
$local_type $var_name;
661
END
662
}
663
664
return "base";
665
}
666
667
668
sub generate_type_function_header {
669
my $out = shift;
670
my $function_name = shift;
671
672
print $out <<END;
673
674
static void $function_name(void)
675
{
676
//Locals
677
END
678
679
}
680
681
sub generate_type_function_footer {
682
my $out = shift;
683
684
#Footer of function
685
print $out <<END;
686
687
}
688
END
689
}
690
691
sub generate_post_local_header {
692
my $out = shift;
693
my $type = shift;
694
my $op = shift;
695
696
print $out <<END;
697
698
cout << "START SECTION $type $op" << endl;
699
END
700
}
701
702
703
sub generate_main_function
704
{
705
706
# Header of main function
707
print $out <<END;
708
709
int main(int argc, char * argv[])
710
{
711
END
712
713
#Call each function in turn
714
foreach my $function (@function_list) {
715
print $out <<"END"
716
717
${function}();
718
719
END
720
721
}
722
723
#Footer of main method
724
print $out <<END;
725
726
return 0;
727
}
728
729
END
730
731
}
732
733
734
735
sub generate_file_header
736
{
737
# Print the header
738
print $out <<END;
739
740
/* Automatically generated by generate_test_suit.pl. */
741
742
/* DO NOT MODIFY THIS GENERATED FILE. CHANGE THE generate_test_suite.pl SCRIPT INSTEAD */
743
744
#include <iostream>
745
746
#include "j9_types.hpp"
747
748
using namespace std;
749
750
END
751
752
}
753
754
755
756