-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgen_opcode2name
executable file
·107 lines (96 loc) · 3.3 KB
/
gen_opcode2name
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
#! /usr/bin/env perl
###################################################
# Helper library for computing bytes:flops ratios #
# (script to generate opcode -> string mapping) #
# #
# By Scott Pakin <[email protected]> #
###################################################
use File::Basename;
use File::Temp qw(tempfile);
use warnings;
use strict;
# Parse the command line.
my $progname = basename $0;
my $usagestr = "Usage: $progname <cpp> CPP | NUM | NUM_POW2\n";
die $usagestr if $#ARGV != 1;
my ($cpp, $want) = @ARGV;
die $usagestr if $want !~ /^(CPP|NUM|NUM_POW2)$/;
# Find Instruction.def.
open(INST_DEF, "/bin/echo '#include <llvm/IR/Instruction.def>' | $cpp - |") || die "${progname}: $!\n";
my $inst_def;
while (my $oneline = <INST_DEF>) {
$inst_def = $1, last if $oneline =~ m,^\# \d+ \"([^\"]+/Instruction\.def)\",;
}
close INST_DEF || die "${progname}: $!\n";
die "${progname}: Failed to find Instruction.def\n" if !defined $inst_def;
# Create a dummy C file that we'll preprocess.
my ($cfile, $cfilename) = tempfile("op2nm-XXXXXX",
SUFFIX => ".c",
TMPDIR => 1,
UNLINK => 1);
open(INST_DEF, "<", $inst_def) || die "open(\"$inst_def\"): $!\n";
while (my $oneline = <INST_DEF>) {
if ($oneline =~ /^\#define (HANDLE_\w+_INST)\((\w+),\s*(\w+),\s*(\w+)\)\s*$/) {
my ($macro, $num, $opcode, $class) = ($1, $2, $3, $4);
print $cfile "#define $macro($num, $opcode, $class) ${progname}: $num $opcode\n";
}
}
close INST_DEF;
print $cfile "#include \"$inst_def\"\n";
close $cfile;
# Preprocess the C file to acquire a mapping from numbers to names.
my @opcode_names;
open(PREPROC, "$cpp $cfilename|") || die "${progname}: $!\n";
while (my $oneline = <PREPROC>) {
$opcode_names[$1] = $2 if $oneline =~ /^${progname}: (\d+) (\w+)$/;
}
close PREPROC || die "${progname}: $!\n";
# If the user requested "NUM", output the number of opcodes.
my $num_names = @opcode_names;
if ($want eq "NUM") {
print $num_names, "\n";
exit;
}
# If the user requested "NUM_POW2", output the number of opcodes plus two
# (adding "constant argument" and "no argument") rounded up to a power of 2.
if ($want eq "NUM_POW2") {
my $num_names_pow2 = $num_names + 2 - 1;
for (my $i = 1; $i <= 32; $i <<= 1) {
$num_names_pow2 |= $num_names_pow2 >> 1;
}
$num_names_pow2++;
print $num_names_pow2, "\n";
exit;
}
# If the user requested "CPP", output C++ code with a static array of name
# mappings. We include two additional pseudo-opcodes, "constant operand" and
# "no operand".
push @opcode_names, ("[Constant]", "[Missing]");
print <<"BOILERPLATE";
/*
* Helper library for computing bytes:flops ratios
* (mapping from opcodes to names)
*
* WARNING: This is a generated file. DO NOT EDIT.
* Edit $progname instead.
*
* By Scott Pakin <pakin\@lanl.gov>
*/
namespace bytesflops {
// Define a mapping from an LLVM opcode number to the
// name of that opcode.
const char* opcode2name[] = {
BOILERPLATE
;
foreach my $num (0 .. $#opcode_names) {
my $name = $opcode_names[$num];
my $comment = sprintf "%3d", $num;
if (!defined $name) {
$name = "Byfl_bug_$num";
$comment .= " (should never be used)";
}
my $string = sprintf " \"%s\"%s", $name, $num < $#opcode_names ? "," : "";
printf "%-25.25s // %s\n", $string, $comment;
}
print " };\n\n";
print "} // namespace bytesflops\n";