I'm filing this as a bug report, but it could just be that
I don't understand how underscore arguments to :multi are
supposed to work.
I'm guessing that an underscore argument in :multi is
intended to indicate a "don't care" argument.  Here's a
simple test program:
    $ cat multi.pir
    .sub main :main
        .local pmc asub
        asub = get_global 'main'
    
        $P0 = new .String
        $P0 = 'hello'
        foo($P0, asub)         # call :multi(_, Sub)
    
        foo(1, asub)           # call :multi(int, Sub)
    
    .end
    
    
    .sub foo :multi(_, Sub)
        .param pmc x
        .param pmc y
        print x
        print " "
        say ":multi(_, Sub)"
    .end
    
    
    .sub foo :multi(int, Sub)
        .param int x
        .param pmc y
        print x
        print " "
        say ":multi(int, Sub)"
    .end
    
    $ ./parrot multi.pir
    hello :multi(_, Sub)
    1 :multi(int, Sub)
    $
   
Unfortunately, the "_" in :multi doesn't seem to match a
string register or string constant argument, instead producing
a "Null PMC access in invoke()" error:
    $ cat multi.pir
    .sub main :main
        .local pmc asub
        asub = get_global 'main'
    
        $P0 = new .String
        $P0 = 'hello'
        foo($P0, asub)         # call :multi(_, Sub)
    
        foo(1, asub)           # call :multi(int, Sub)
    
        foo('world', asub)     # should call :multi(_, Sub)
    .end
    
    
    .sub foo :multi(_, Sub)
        .param pmc x
        .param pmc y
        print x
        print " "
        say ":multi(_, Sub)"
    .end
    
    
    .sub foo :multi(int, Sub)
        .param int x
        .param pmc y
        print x
        print " "
        say ":multi(int, Sub)"
    .end
    
    $ ./parrot multi.pir
    hello :multi(_, Sub)
    1 :multi(int, Sub)
    Null PMC access in invoke()
    current instr.: 'main' pc 40 (multi.pir:11)
    $                                                                         
   
Is this a bug (I think it is), or does the underscore in
:multi mean something other than "any argument"?
If it's a bug, I can add a few tests to t/pmc/multisub.t .
Pm
The meaning is 'any PMC' [1], and it of course can't be a bug as there are no 
specs ;)
leo
[1] multi_type:
compilers/imcc/imcc.y:729 ff
 ...
 r = mk_const(interp, str_dup("PMC"), 'S');
Implementing '_' as 'any type' wouldn't be that hard. Except the mentioned 
imcc.y snippets[1], it'll need some native any type and adjustments in
  static UINTVAL
  mmd_distance(Interp *interp, PMC *pmc, PMC *arg_tuple)
near
        /*
         * different native types are very different, except a PMC
         * which matches any PMC
         */
        if ((type_sig <= 0 && type_sig != enum_type_PMC) || type_call <= 0) {
[1]
compilers/imcc/imcc.y:729 ff
leo
I'll take the position that implementing '_' as 'any type' is
the semantic we really want here.  We already have a way to
say 'any PMC':
.sub foo :multi(pmc)
Here's a more detailed use case of why the current semantics
aren't useful.  For subroutine calls, PAST-pm tries to pass
constants directly to subroutines (when it can) rather than 
creating temporary PMCs and passing those.  For example, a HLL 
expression such as
3 .op. 4
gets turned into PIR like
$P0 = "infix:.op."(3, 4)
instead of
    $P0 = new .Integer
    assign $P0, 3
    $P1 = new .Integer
    assign $P0, 4
    $P2 = "infix:.op."($P0, $P1)
The present case I've run into is the Perl 6 "smart match"
operator (infix:~~), where the operation to be performed depends
on the types of the arguments.  For example, a pattern match
is defined as:
.sub "infix:~~" :multi(_, Sub)
For an expression such as $x ~~ /abc/, this works okay:
    find_lex $P0, '$x'             # get $x
    find_name $P1, 'abc_sub'       # get sub for /abc/
    $P2 = "infix:~~"($P0, $P1)     # call infix:~~
But for something like 'abc' ~~ /abc/, we end up with
    find_name $P1, 'abc_sub'       # get sub for /abc/
    $P2 = "infix:~~"('abc', $P1)   # call infix:~~
and it won't find the :multi(_, Sub) given above.  So far I've
only found two workarounds -- one is to convert all arguments
to PMCs before calling any sub (this is what PAST-pm is
doing now), the other is to create additional 
:multi(string|int|num, ...) subs that redispatch to the '_' 
version:
.sub "infix:~~" :multi(int, Sub)
        .param pmc x
        .param pmc y
        .return "infix:~~"(x, y)
    .end
.sub "infix:~~" :multi(string, Sub)
        .param pmc x
        .param pmc y
        .return "infix:~~"(x, y)
    .end
# etc.
The first approach basically means we build a PMC for
every constant value, the second means that we end up
with three additional subs for every underscore in :multi.
And from a PIR-programmer perspective I don't see a lot
of downside to having '_' mean 'any value', but I can't
speak to the difficulty of implementing this in imcc.
Pm
> Here's a more detailed use case of why the current semantics
> aren't useful.  For subroutine calls, PAST-pm tries to pass
> constants directly to subroutines (when it can) rather than
> creating temporary PMCs and passing those.  For example, a HLL
> expression such as
>
>     3 .op. 4
>
> gets turned into PIR like
>
>     $P0 = "infix:.op."(3, 4)
>
> instead of
>
>     $P0 = new .Integer
>     assign $P0, 3
>     $P1 = new .Integer
>     assign $P0, 4
>     $P2 = "infix:.op."($P0, $P1)
I read through the multi code last night (ow!) and don't see any reason not to 
make the primitive types and their related PMCs equivalent in the distance 
value function.
Of course, I severely distrust the distance value function after it finds the 
distance for Pheme's best-matched 'atom?' variant at MMD_BAD_DISTANCE and 
gets progressively worse for the others.
-- c