IRC channel logs
2025-04-11.log
back to list of logs
<old>does Guile have optimization passes on the bytecode? <old>Something like peephole optimization <mwette> lechner: you should be able to initialize conv using a guile pointer (to a C function) or a lamda, if I read it correctly. I've been off of nyacc for a bit <mwette>old: check modules/language/cps/ <lechner>mwette / Hi, to get my callbacks to work I have to first re-enter Guile in a small C wrapper. The callback is called from a dynamically loaded, shared ELF object. Is that something that could be fixed in Guile? <lechner>without it, i get inconsistent errors. they indicate I'm still in libguile, showing a variety of Guile-like error messages, but things are not resolved properly <lechner>it seems like a small bug in procedure->pointer to me, near where the closure is calculated <lechner>Hi, do both procedure->pointer and foreign-library-pointer return boxed pointer objects? <lilyp>procedure->pointer should return a raw pointer <lechner>lilyp / what is a raw pointer? procedure->pointer in foreign.c returns an SCM object, I think pointer = scm_from_pointer (executable, ffi_closure_free); <lechner>and is pointer-address the way to unbox it? <lechner>I always forget about the REPL. Both return boxed pointers <old>mwette: my understanding of CPS is that this is similar to optimization applied to AST no? Peephole optimization are directly applied on the generate bytecode. There's no control flow involve <mwette>you said "something like"; I pointed you to the optimization I have seen; you could look at the assembler in system/vm but I don't recall seeing anything there; didn't know where peephole goes <mwette>I think procedure->pointer returns a boxed pointer object, indicated by <pointer xxxx>, you use pointer-address to get the integer address value <lechner>mwette / thanks so much! my issue may have been garbage collection <lechner>Hi, can a parameter be a good strategy to avoid garbage collection when one loses scope of a variable? <old>lechner: what are you trying to achieve? Protecting a procedure sent to C? <lechner>old / yes, across shared library calls but i don't want to expose this low level handler in the API. instead my low-level handler calls a higher-level handler given by the caller <old>I see. This happen often with lambda procedures <old>for example, callbacks in C <old>IIRC, taking the pointer of the procedure does not protect it from GC <old>so you need to box the procedure in a hashtable <old>so say you are adding callback to some C library. You add the procedure in the hashtable first then pass it to C. You can then return something to remove the callback if necessary <old>Could be a symbol, a cookie or a thunk wathever <lechner>Hi, what do I do when an argument to my callback appears as <pointer 0x1> instead of the integer 1, please? <old>What's the signature of the C function? <lechner>and the two pointers in the middle are passed as int! <old>so you have something like: (procedure->pointer int my-conv (list int '* '* '*)) ? <old>And it's the C library that is calling this procedure? <old>so I assume you have a procedure like: (lambda (num-msg msg resp appdata-ptr) ...) <old>so which argument is <pointer 0x1>? <lechner>yes, on all. num_msg is <pointer 0x1> <lechner>and msg and resp are int. appdata_ptr is always correct, namely a null #<pointer 0x0> <old>hmm that's weird. I suppose these pointer are structure allocated by the C library <old>this looks like a ABI mismatch <lechner>old / i can use pointer-address and make-pointer to convert, but Guile has them wrong <old>but you would end it with the same pointer if do that <old>you are saying that in your procedure callback, you have <pointer 0x1> as an argument? <old>as a paremter directly received from C <lechner>no, convert the int with (pointer-address #<pointer 0x1>) and get the pointers in the middle with make-pointer <lechner>yes, i have #<pointer 0x1> as an argument <old>that's look like a problem from the library side then <old>or ABI mismatch. If your callback is not the same signature as the library expected <old>I see that struct pam_conv is expecting a void *appdata_ptr; <lechner>it is, i think. isn't the convention that ints are passed directly and pointers to everything else? why does Guile think the first one is a pointer? <old>can you set appdata_ptr to something like (make-pointer #xdeadbeef) and see if you get the same pointer in your callback? <old>num-msg should be a number if the signature is (list int '* '* '*) <old>do you mind sharing your code so I can have a quick peek? <lechner>the deadbeef pointer works but that value comes from guile <lechner>I'm not even sure how Guile know what each parameter is <old>well regarding the gc, you should be fine since this procedure is globally defined <old>for the num-msg argument <old>it really should be a number, no need anything else <old>(pk fake_num_msg) should print: ;; (1) <lechner>how does Guile know what type it is being passed? <old>it does not. It respect the ABI as defined by (list int '* '* '*) <old>internally, Guile use libffi <old>which understand the calling convention of the architecture you are on. I assume x86-64 <old>so it knows that the first argument will be in register %rdi, the second in %rsi and so on <lechner>yes, but it cannot know the type? the signature is not part of conversation-function <old>then Guile receive these values as raw integer and will convert them to a object representation <old>yes it it. (list int '* '* '*) <old>it tells guile to interpret the first argument as an integer. Actually it tells libffi that and then Guile will interpret the result as a number <old>so really the first argument should be number. But the other pointers because that's what you expect <old>you could for example replace the '* with uintptr_t <old>then you will only receive number <old>you can then interpret these numbers as address by invoking make-pointer <lechner>okay, don't know much about libffi. procedure->pointer registers the callback somewhere with that signature so Guile (or libffi) knows types when the call comes in? <lechner>well, that's obviously not working here <old>actually the pointer returned by Guile is some kind of wrapper trampoline that will jump to your procedure <old>with the arguments decoded for you, respecting the ABI specifies <old>try changing all the '* for uintptr_t <old>if you see any <pointer> in one of your argument that would be _very_ strange <old>it seems like the callback in C is still pointing to the same pointer? <old>Did you try in a fresh process to see if there's change? <lechner>it's an executable that runs anew each time I change something <lechner>well, the trampoline never got it right in the first place, so perhaps you are asking too much! <old>I don't really understand. Looking at your code, it should work <old>at least you should have a plain integer as fake_num_msg <old>I see that you're using nyacc, which I'm not familiar with <old>so perhaps there's something there, but I doubt <lechner>old / yesterday I called a custom C routine with the procedure pointer and then used the appdata_ptr to transfer the trampoline pointer. same problem, I think, but i will try again https://bpa.st/PDBA <lechner>old / same problem when I go that route. <lechner>is there anything interesting i can do with the trampoline pointer from C? <old>SCM scm_entry_point = scm_pointer_to_procedure (scm_int_type, scm_appdata_ptr, scm_parameter_types); <old>this does not make sens <old>scm_appdata_ptr should be scm_entrypoint_ptr <old>but the procedure you want to call <lechner>old / it is. that's the trampoline pointer. i changed the guile code <old>or are you passing the procedure pointer in appdata_ptr? <lechner>the procedure pointer and the trampoline pointer are the same thing, right? <old>no they are not the same <old>(program-code procedure) != (procedure->pointe procedure) <lechner>okay, i have never used program-code <old>procedure->pointer generate a proxy function that will be able to translate C things to Guile thing and call your proecedure <lechner>i did verify that the address is the same in C and Guile, but I think I only deal with the trampoline pointer <lechner>does the trampoline pointer allow any inspection from C? <old>You can probably disassemble it in GDB <old>given the pointer, do (gdb) disassemble pointer <lechner>I'm not sure how to do that. there may be too many layers <old>can you print the address of procedure->pointer before packing it with nyacc and then print the address you have in C? <old>in GDB, break in pam_conv_entry_point <old>dissasemble appdata_ptr <lechner>i don't know how to start gdb on a guile program <old>but what's the value print here: (pk (procedure->pointer int conversation-function ;; (make-conversation-function message-handler) (list int uintptr_t uintptr_t uintptr_t))) <old>before packing it with cdata-set! <old>I can't see what is problematic <lechner>okay, thanks! it's either nyacc or my weird shared library library stuff. the callback is called by an ELF module (pam_unix.so) that was dynamically loaded by Guile-PAM (the thing we are debugging) which was loaded by an ELF module that starts libguile (pam_guile.so) which is called by a shared library (libpam.so) that was loaded by my test program <lechner>could the nested call to libguile mess things up or does it simply stand down when the executable is already in Guile mode? <ArneBab>dthompson: that’s also true (code assignment, and it’s ok for me if you use that to get it into Guile) for everything I have in the wisp repo. In the examples there are a few things I’d love to contribute, but I have a hard time contributing them. https://hg.sr.ht/~arnebab/wisp/browse/examples/ <lechner>ArneBab / thanks for waiting, and sorry we took up so much space <mwette>lechner: one BIG issue with cdata is that it uses bytevectors. Guile's GC does not scan bytevectors for pointers :(. I wish Guile had a make-bytevector/pointers. <mwette>^ the issue is not bytevectors per se but the fact that c data structures contain pointer that point to, e.g., callbacks <mwette>i have thought about how to fix, but make-bytevector/pointers would be better <lechner>mwette / thanks! i think my issues are probably unrelated to Nyacc at this point <ArneBab>lechner: no problem: this channel is for talking, not for saving space ☺ <lechner>mwette / Hi, does cdata* dereference a cpointer while staying in <cdata>? <lechner>Hi, how may I convert, for experimental purposes, a signed int to an unsigned int, please? It's pointer value that was mistakenly delivered as a signed int <lechner>nvm, i subtracted from 4294967294 for my arch <rlb>Is print-set! broken in 3.0 atm, or am I just missing something? <rlb>scheme@(guile-user)> (print-set! r7rs-symbols #t) <rlb>While compiling expression: <rlb>In procedure print-options-interface: Unknown option name: #t <rlb>And putting an fprintf of name in change_option_setting() prints "nothing" for each name. <rlb>...yeah, something is clobbering the scm_print_opts names (at least). <rlb>ohh, hmm, it's more complicated than I realized, we're hiding an SCM in a char* -- I wonder how the gc knows about that. <rlb>We might have a marking function somewhere I suppose... <rlb>oh, it's probably interned <rlb>Ohh, right, I think I've hit this before -- that interface is just surprising (to me), i.e. it sounds like you're only supposed to provide values for booleans, e.g. (print-set! highlight-prefix "..." r7rs-symbols), but if that's so, then how could you *unset* a boolean value, and why do the docs mention (print-set! quote-keywordish-symbols #f)? <lechner>mwette / okay, i have something that works. just to confirm, please: (make-cdata type) allocates space for an instance of that type, right? <old>ArneBab: are wisp module compatible with Scheme module? <old>for example, IIRC, the Javascript language was just not usable because you could not reference symbol, thus module, that have a hyphen in it <old>So, can I import a wisp module and use it in Scheme and vice-versa? <lechner>mwette / thank you! great software, and great support! please have a good weekend! <lilyp>more generally, wisp treats hyphens just like scheme does