ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/OpenCL/gengetinfo
Revision: 1.17
Committed: Sat May 5 13:30:07 2012 UTC (12 years ago) by root
Branch: MAIN
Changes since 1.16: +2 -0 lines
Log Message:
*** empty log message ***

File Contents

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