ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/OpenCL/gengetinfo
Revision: 1.7
Committed: Thu Apr 19 13:06:55 2012 UTC (12 years, 1 month ago) by root
Branch: MAIN
Changes since 1.6: +4 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #!/opt/bin/perl
2
3 # almost every "if" or "?" in this file indicates a place where the OpenCL
4 # designers fucked it up - each time you have to remember an exception to
5 # the naming rules.
6
7 use common::sense;
8
9 my %classmap = qw(
10 platform Platform
11 device Device
12 context Context
13 event Event
14 profiling Event
15 mem Memory
16 image Image
17 gl_texture Image
18 sampler Sampler
19 program Program
20 program_build Program
21 kernel Kernel
22 kernel_work_group Kernel
23 command_queue Queue
24 );
25
26 my %typemap = (
27 cl_bool => ['cl_bool', 'value [i] ? &PL_sv_yes : &PL_sv_no', 'boolean'],
28 #char => ['char', 'newSVpvn (value, size)', 'string'],
29 char => ['char', 'newSVpv (value, 0)', 'string'], # all these are 0-terminated strings, and the driver often appends a \0
30 size_t => ['size_t', 'newSVuv (value [i])', 'int'],
31 "void*" => ['void *', 'newSVuv ((IV)(intptr_t)value [i])', 'ptr_value'],
32 cl_platform_id => ['cl_platform_id', 'OpenCL::Platform'],
33 Context => ['cl_context', 'OpenCL::Context', 'ctx'],
34 Device => ['cl_device_id', 'OpenCL::Device', 'device'],
35 cl_device_id => ['cl_device_id', 'OpenCL::Device', 'device'],
36 Memory => ['cl_mem', 'OpenCL::Memory', 'mem'],
37 Program => ['cl_program', 'OpenCL::Program', 'program'],
38 CommandQueue => ['cl_command_queue', 'OpenCL::Queue', 'queue'],
39 cl_context_properties => ['cl_context_properties', 'newSVuv ((UV)value [i])', 'property_int'],
40 );
41
42 {
43 my %tmap = (
44 T_IV => "newSViv (value [i])",
45 T_UV => "newSVuv (value [i])",
46 );
47
48 open my $fh, "<typemap"
49 or die "typemap: $!";
50
51 while (<$fh>) {
52 next if /^INPUT$/;
53 my ($name, $type) = split /\s+/, $_;
54 if ($tmap{$type}) {
55 $typemap{$name} = [$name, $tmap{$type}, substr $name, 3];
56 }
57 }
58 }
59
60 sub patch($$$$) {
61 my ($file, $beg, $end, $contents) = @_;
62
63 {
64 local $/;
65
66 open my $fh, "<$file"
67 or die "$file: $!";
68
69 my $data = <$fh>;
70 $data =~ s/^(\Q$beg\E\n).*?\n(\Q$end\E\n)/$1\n$contents$2/sm
71 or die "$file: couldn't find $beg/$end";
72
73 open my $fh2, ">$file~"
74 or die "$file~: $!";
75
76 syswrite $fh2, $data;
77 }
78
79 rename "$file~", $file;
80 }
81
82 for my $CLASS (qw(platform device context command_queue mem image sampler program program_build kernel kernel_work_group event profiling gl_texture)) {
83 open my $fh, "<getinfo.txt"
84 or die "getinfo.txt: $!";
85
86 my $POD;
87 my @funcs;
88 my %alias;
89
90 while (<$fh>) {
91 chomp;
92 my ($class, $name, $ctype) = split /,\s*/, $_, 3;
93 next unless $class eq "cl_$CLASS\_info";
94 next if $name eq "CL_IMAGE_FORMAT"; # struct
95 next if $name eq "CL_PROGRAM_BINARIES"; # needs multiple calls
96
97 $ctype =~ s/cl:://g;
98 $ctype =~ s/::size_t/size_t/g;
99
100 my $cbase = $class;
101 $cbase =~ s/_(.)/\U$1/g;
102 $cbase =~ s/^cl//;
103 $cbase =~ s/Info$//;
104 $cbase = "MemObject" if $cbase eq "Mem";
105 $cbase = "EventProfiling" if $cbase eq "Profiling";
106
107 my $real_class = $CLASS;
108 $real_class = "program" if $real_class eq "program_build";
109 $real_class = "kernel" if $real_class eq "kernel_work_group";
110 $real_class = "event" if $real_class eq "profiling";
111
112 my $perl_name = lc $name;
113 $perl_name =~ s/^cl_//;
114 $perl_name =~ s/^$real_class\_//;
115 $perl_name =~ s/^queue\_//;
116
117 my $extra_args;
118 my $extra_perl_args;
119 my $extra_xs_args;
120
121 if ($CLASS eq "program_build" || $CLASS eq "kernel_work_group") {
122 $extra_args = ', device';
123 $extra_perl_args = ' ($device)';
124 $extra_xs_args = ', OpenCL::Device device';
125 }
126
127 my $dynamic;
128 my $nelem = "size / sizeof (*value)";
129
130 if ($ctype eq "STRING_CLASS") {
131 $ctype = "VECTOR_CLASS<char>";
132 $nelem = "1";
133 $dynamic = 1;
134 }
135
136 my $type = $ctype;
137 my $array = 0;
138
139 if ($type =~ s/^VECTOR_CLASS<\s*(.*)>$/$1/) {
140 $dynamic = 1;
141 $array = 1;
142 } elsif ($type =~ s/<(\d+)>$//) {
143 $dynamic = 1;
144 $array = 1;
145 }
146
147 $type = $typemap{$type}
148 or die "$name: no mapping for $ctype";
149
150 my $perltype = $type->[2];
151
152 if ($array && $nelem ne "1") {
153 $perltype = "\@${perltype}s";
154 } else {
155 $perltype = "\$$perltype";
156 }
157
158 $POD .= "=item $perltype = \$$real_class->$perl_name$extra_perl_args\n\nCalls C<clGet${cbase}Info> with C<$name> and returns the result.\n\n";
159
160 # XS1 contains the function before ALIAS, XS2 the function afterwards (the body)
161 # after we generate the bdoy we look for an identical body generated earlier
162 # and simply alias us to the earlier xs function, to save text size.
163 my ($XS1, $XS2);
164
165 $XS1 = "void\n"
166 . "XXXNAMEXXX (OpenCL::$classmap{$real_class} self$extra_xs_args)\n";
167 $XS2 = " PPCODE:\n";
168
169 if ($dynamic) {
170 $XS2 .= " size_t size;\n"
171 . " NEED_SUCCESS (Get${cbase}Info, (self$extra_args, ix, 0, 0, &size));\n"
172 . " $type->[0] *value = tmpbuf (size);\n"
173 . " NEED_SUCCESS (Get${cbase}Info, (self$extra_args, ix, size, value, 0));\n";
174 } else {
175 $XS2 .= " $type->[0] value [1];\n"
176 . " NEED_SUCCESS (Get${cbase}Info, (self$extra_args, ix, sizeof (value), value, 0));\n";
177 }
178
179 if ($array && $nelem ne "1") {
180 $XS2 .= " int i, n = $nelem;\n"
181 . " EXTEND (SP, n);\n"
182 . " for (i = 0; i < n; ++i)\n";
183 } else {
184 $XS2 .= " EXTEND (SP, 1);\n"
185 . " const int i = 0;\n"
186 }
187
188 if ($type->[1] =~ /^OpenCL::(\S+)$/) {
189 my $oclass = $1;
190 $oclass = "MemObject" if $oclass eq "Memory";
191 $oclass = "CommandQueue" if $oclass eq "Queue";
192
193 $XS2 .= " {\n";
194 $XS2 .= " NEED_SUCCESS (Retain$oclass, (value [i]));\n" unless $1 eq "Platform" || $1 eq "Device";
195 $XS2 .= " PUSHs (NEW_MORTAL_OBJ (\"$type->[1]\", value [i]));\n";
196 $XS2 .= " }\n";
197 } else {
198 $XS2 .= " PUSHs (sv_2mortal ($type->[1]));\n";
199 }
200
201 $XS2 .= "\n";
202
203 if (my $alias = $alias{"$XS1$XS2"}) {
204 push @$alias, [$perl_name, $name];
205 } else {
206 push @funcs, [$XS1, (my $alias = [[$perl_name, $name]]), $XS2];
207 $alias{"$XS1$XS2"} = $alias;
208 }
209 }
210
211 my $XS;
212
213 # this very dirty and ugly code is a very dirty and ugly code size optimisation.
214 for (@funcs) {
215 $_->[0] =~s /^XXXNAMEXXX/$_->[1][0][0]/m;
216
217 if (@{ $_->[1] } == 1) { # undo ALIAS
218 $_->[2] =~ s/\bix\b/$_->[1][0][1]/g;
219 $_->[1] = "";
220 } else {
221 $_->[1] = " ALIAS:\n" . join "", map " $_->[0] = $_->[1]\n", @{ $_->[1] };
222 }
223 $XS .= join "", @$_;
224 }
225
226 warn "patching class $CLASS\n";
227
228 patch "OpenCL.xs", "#BEGIN:$CLASS" , "#END:$CLASS" , $XS;
229 patch "OpenCL.pm", "=for gengetinfo begin $CLASS", "=for gengetinfo end $CLASS", $POD;
230 }
231