freenode/#clasp - IRC Chatlog
Search
19:22:07
Bike
void llvm_sys__ste_calling_conv(T_sp obj, ClaspCallingConv conv) { if (gc::IsA<CallBase_sp>(obj)) { gc::As_unsafe<CallBase_sp>(obj)->wrappedPtr()->setCallingConv(conv); ...
19:23:51
drmeister
And this won't work because the setCallingConf takes a llvm::CallingConv::ID, which is a typedef for uint8_t - right?
19:24:27
Bike
right. i mean, it "works" in the sense that you can then pass it a number instead of an enum symbol
19:26:49
drmeister
CL_EXTERN_DEFMETHOD(CallBase_O, (void (*)(llvmo::ClaspCallingConv))&CallBase_O::ExternalType::setCallingConv);
19:27:24
drmeister
I'm not sure it will work. I've used these method pointer casts to select overloaded methods.
19:28:31
drmeister
Here I'm trying to convince the compiler to cast the function pointer to one that takes a ClaspCallingConv as the argument. The argument doesn't need to be converted because your enums have the same integer values as the original llvm::CallingConv::ID values - right?
19:29:39
Bike
will it work with getCallingConv too, do you think? so only the return type is different
19:32:01
drmeister
In C++ you aren't allowed to overload function/method names that only differ in their return type. That touches on this but it shouldn't cause us any problems. We are casting one function pointer into another function pointer with a type that the compiler can use to find an appropriate translator. The llvm::CallingConv::ID and llvmo::ClaspCallingConv are bitwise identical.
19:42:37
Bike
we're not casting it to a void*, are we? we're casting it to another function pointer, so it's fine
20:22:40
Bike
and was talking about the possibility of another entry point to handle varargs but didn't take a closure
20:23:13
karlosz
https://github.com/clasp-developers/clasp/commit/370c82f80f6000350c132f0aa6feda0122a8b06a
20:24:04
karlosz
that way we never need to cons closure vectors for any type of local call no matter the lambda list
20:31:15
karlosz
so i implemented if-if elimination the other day and noticed for (If (not x) ... ...) the fact that we get f->m and m->f pairs sort of blocked the optimization
20:31:48
karlosz
its not that delete-transmission doesn't work anymore, its just that when the metaevaluator is simplifiying the flow graph those pairs can come into existence
20:32:37
karlosz
then the metaevaluator simplifies the flow graph and you get those next to each other
20:33:15
karlosz
so i was thinking by pushing f->m and m->f coercion instructions later we wouldn't have to worry about having to eliminate pairs of those instructions all the time
20:33:59
karlosz
unlike with constant reference it doesn't seem like an high level optimizations will ever take advantage of the fact that those instructions are "there"
20:34:47
karlosz
and those coercion instructions seem like they can be recovered from the rtype/ctypes of the computations anyway
20:34:51
Bike
sure. that's why i'm working on mv calls. then we can only use mtf and mtf when it's part of the semantics.
20:42:03
Bike
this isn't working with SyncScope for some reason. error in some file i haven't touched
21:10:45
Bike
annoying wrinkle here: error messages from the argument parsing code use the closure (unsurprisingly)
21:10:58
Bike
we can check if the call is valid ahead of time, except for keywords i guess, in general
21:12:06
Bike
maybe cleavir can have some kind of hook for what calls to local-call-ify... eck... i was hoping to be able to skip lambda list parsing in cleavir as much as possible
21:30:23
Bike
cos it's kind of nice for the error object to be able to reference a function, i guess.
21:30:26
karlosz
also, the idea is that we check ahead of time and only signal a warning at compile time but still leave a runtime error
21:30:50
Bike
sure, but we can't check keyword arguments, in the weird case of having variable keywords
21:32:29
karlosz
in python they just don't local call convert anything with &rest or variable keyword args
21:34:10
Bike
but we could just allocate a closure for the error, or not include a function object in the error. i think if cleavir marked all local calls that would be nice, there are things that can be done with that information.
21:34:46
Bike
the question of how to actually do the call is sort of lower level? like the choice of calling convention. maybe we can do that in some nice way since you were having it so that uh... i wasn't totally clear on how closures were allocated actually
21:34:56
Bike
i thought you wanted it so that each reference of a local function would get its own allocation'
21:59:00
Bike
maybe we could separate the closure-allocation consequences of local-call from the "here's the function, you can inline or whatever" aspect
22:36:12
karlosz
Bike: i kinda changed my mind on that. that's how they do it in cmucl, but it's pseudo-spec-violating
22:36:32
karlosz
since you lose EQ-ness of the function object if you cons a new one on each reference
22:37:01
karlosz
it would be super nice if we could do it so we simplify the mutually closing over labels handling
23:01:21
Bike
yeah. i don't remember the details so much. but like (make-hash-table :test #'eq) failed because the #'eq wasn't the same as the global function
23:16:33
Bike
i was lookinag at changing how multiple values are handled, and expanding multiple-value-call optimizations
23:16:39
drmeister
This is the buildbot for the last couple of days using bir and compile-file-parallel
23:20:00
drmeister
Where is the generic function discriminating interpreter defined? We have one in C++ right?
23:23:46
drmeister
So we don't have an interpreted generic function discriminator class? Did we have one and you changed it to a bytecode interpreter?
23:25:30
drmeister
I thought we had a special C++ class that could be setup to evaluate a discriminating function
23:26:57
Bike
we just have a normal funcallable instance, with the interpreter as its discriminating function.
23:28:39
drmeister
Here's what I'm musing about. We have these crap single-dispatch-generic functions that we can replace with interpreted-discriminating-functions.
23:29:50
drmeister
We can create generic-functions with satiated call histories/specializer profiles that dispatch to C++ methods based on the type of the single argument that it would dispatch on.
23:31:42
drmeister
But we have the usual bootstrapping problem - we can't do this until we have certain facilities in place. We need the aclasp/bclasp compiler
23:45:43
drmeister
If we change those two functions so that they generate something that clos__interpret_dtree_program(SimpleVector_sp program, T_sp generic_function, VaList_sp args) can use...
23:46:14
drmeister
Then I think we can get rid of the SingleDispatchxxx code and use generic functions for C++ methods.
23:48:52
drmeister
This would speed up calling of C++ methods and allow us to compile the discriminating functions if we want to.
1:44:41
drmeister
I'm proposing to replace SingleDispatchGeneric functions with the same dtrees we use for generic functions. It will simplify calling C++ methods - and probably speed it up a bit.
1:45:28
drmeister
I think the simplest way to do it is to get rid of SingleDispatchGenericFunctions and use generic functions in their place.
1:45:57
drmeister
When we expose methods we build up a bogus call-history for the generic function that maps argument types to effective methods (wrapped C++ methods).
1:46:47
drmeister
We then write a function like clos__interpret_dtree_program but it uses the call history to do the dispatch.
1:47:19
drmeister
It will be slower when we are building aclasp - but once aclasp is up we can compile the call histories to dtree programs.
1:48:04
drmeister
The dtree bytecode for these C++ methods should be pretty simple - so we could do that.
1:49:08
drmeister
But we could write a printer for dtree programs and that would make it easier to understand them.
1:49:56
Bike
it's honestly pretty simple. it does the old binary search whatever stuff and then calls a function or whatever
1:50:02
drmeister
There are no EQL specializers and the only types we need to worry about are General_O derived types.
1:51:28
drmeister
We could - but why bother. We do need a specialized dtree compiler then, implemented in C++ so that we can generate the dtree programs at startup.
1:53:42
drmeister
Right - so we could just write an interpreter that searches that alist for a type match and then calls the appropriate effective method.
1:54:12
drmeister
Once the dtree compiler is available we compile all of the call histories and then install the dtree interpreter.
1:57:11
drmeister
As an intermediate step we can continue to use the SingleDispatchGenericMethod object I think.
2:18:39
drmeister
The car's of each entry are a vector of classes representing the classes of the arguments