OpenCL
view release on metacpan or search on metacpan
$perl_name =~ s/^queue\_//;
my $extra_args;
my $extra_perl_args;
my $extra_xs_args;
if ($CLASS eq "program_build" || $CLASS eq "kernel_work_group") {
$extra_args = ', device';
$extra_perl_args = ' ($device)';
$extra_xs_args = ', OpenCL::Device device';
}
if ($CLASS eq "kernel_arg") {
$extra_args = ', idx';
$extra_perl_args = ' ($idx)';
$extra_xs_args = ', cl_uint idx';
}
my $dynamic;
my $nelem = "size / sizeof (*value)";
if ($ctype eq "STRING_CLASS") {
$ctype = "VECTOR_CLASS<char>";
$nelem = "1";
$dynamic = 1;
}
my $type = $ctype;
my $array = 0;
if ($type =~ s/^VECTOR_CLASS<\s*(.*)>$/$1/) {
$dynamic = 1;
$array = 1;
} elsif ($type =~ s/<(\d+)>$//) {
$dynamic = 1;
$array = 1;
}
$type = $typemap{$type}
or die "$name: no mapping for $ctype";
my $perltype = $type->[2];
if ($array && $nelem ne "1") {
$perltype = "\@${perltype}s";
} else {
$perltype = "\$$perltype";
}
(my $perlenum = $name) =~ s/^CL_/OpenCL::/ or die;
$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";
# XS1 contains the function before ALIAS, XS2 the function afterwards (the body)
# after we generate the bdoy we look for an identical body generated earlier
# and simply alias us to the earlier xs function, to save text size.
my ($XS1, $XS2);
$XS1 = "void\n"
. "XXXNAMEXXX (OpenCL::$classmap{$real_class} self$extra_xs_args)\n";
$XS2 = " PPCODE:\n";
my $stype = $type->[0]; # simplified type
$stype = $typesimplify{$stype} while exists $typesimplify{$stype};
if ($dynamic) {
$XS2 .= " size_t size;\n"
. " NEED_SUCCESS (Get${cbase}Info, (self$extra_args, ix, 0, 0, &size));\n"
. " $stype *value = tmpbuf (size);\n"
. " NEED_SUCCESS (Get${cbase}Info, (self$extra_args, ix, size, value, 0));\n";
} else {
$XS2 .= " $stype value [1];\n"
. " NEED_SUCCESS (Get${cbase}Info, (self$extra_args, ix, sizeof (value), value, 0));\n";
}
if ($array && $nelem ne "1") {
$XS2 .= " int i, n = $nelem;\n"
. " EXTEND (SP, n);\n"
. " for (i = 0; i < n; ++i)\n";
} else {
$XS2 .= " EXTEND (SP, 1);\n"
. " const int i = 0;\n"
}
if ($type->[1] =~ /^OpenCL::(\S+)$/) {
my $oclass = $1;
$oclass = "MemObject" if $oclass eq "Memory";
$oclass = "CommandQueue" if $oclass eq "Queue";
my $stash = lc $type->[1];
$stash =~ s/opencl:://;
$stash =~ s/::/_/g;
$XS2 .= " NEED_SUCCESS (Retain$oclass, (value [i]));\n" unless $oclass eq "Platform" || $oclass eq "Device";
$XS2 .= " PUSH_CLOBJ (stash_$stash, value [i]);\n";
} else {
$XS2 .= " PUSHs (sv_2mortal ($type->[1]));\n";
}
$XS2 .= "\n";
if (my $alias = $alias{"$XS1$XS2"}) {
push @$alias, [$perl_name, $name];
} else {
push @funcs, [$XS1, (my $alias = [[$perl_name, $name]]), $XS2];
$alias{"$XS1$XS2"} = $alias;
}
}
my $XS;
# this very dirty and ugly code is a very dirty and ugly code size optimisation.
for (@funcs) {
$_->[0] =~s /^XXXNAMEXXX/$_->[1][0][0]/m;
if (@{ $_->[1] } == 1) { # undo ALIAS
$_->[2] =~ s/\bix\b/$_->[1][0][1]/g;
$_->[1] = "";
} else {
$_->[1] = " ALIAS:\n" . join "", sort, map " $_->[0] = $_->[1]\n", @{ $_->[1] };
}
( run in 0.584 second using v1.01-cache-2.11-cpan-5511b514fd6 )