# 46 — a backtick that means it, native calls, and a bigger default map **the backtick.** a backtick ends the source only outside a comment, a string and a character literal. `srcend` keeps a small state (normal, line comment, block comment, string, char) across `nextch`, so a backtick inside a comment no longer cuts the program off. three comments in the compiler that had one were the failure that showed it (the fixpoint broke), and they were reworded anyway. **a parse word has to read.** a handler run by `kwcall` that never took a token would be called again on the same token forever. `next` counts tokens, and `kwcall` compares the count before and after: no progress is an error ("a parse word has to read its own name with next()"). a fuzz run found it. `tests/langerrors/parseword_noread.zc` keeps it. **lexer.** `isopch` is a 31-bit mask test and `isidc` a range test, `intern` checks the first character before hashing, `readsrc` has a fast path for stdin. the compiler compiles itself about 12% faster. the 64-bit literal that first stood in for the mask lost its top bit (`lit(v)` is `2v+1`), which is why the mask is 31 bits wide. **llvm gets the target.** the module carries the host's triple and data layout, functions carry attributes, and element addresses are `inbounds` GEPs. `noalias` is not valid on vm memory because host helpers read and write it. on the bench kernels the code was already near native, so nothing moved. **native calls.** `extern double pow(double, double);` defines a zc function that calls the c function. the compiler reads a c prototype (`ckind` maps c spellings to kinds), writes the symbol name, a signature word and room for the arguments into the code stream, compiles a small stub from text (the same way `include` compiles a file) that stores its arguments and does `syscall(14, block)`. the host looks the symbol up with `dlsym` (the math library is opened if the first lookup misses) and calls it through a prototype of six longs and eight doubles ending in `...`, so integer and float registers fill independently and a variadic callee sees its register count. kinds: long, double, byte pointer, int, float, word pointer, unsigned int, short, unsigned short, char, unsigned char, and `str` for a zc byte string. a pointer into vm memory is `(char *)m + byte address`, which works because vm memory is one flat array; anything outside the array passes through, so a `malloc` result is an opaque number. `as` now sets the float flag for a cast to `float`, which the stub's result needs. **callbacks.** `cfunc(f)` asks gate op 16 for a native pointer. there are 16 prebuilt c functions per result class (long, double, float), each taking six longs and eight doubles; calling one packs the arguments by the signature, pushes them on the vm data stack under the stacks as they were at the gate store, pushes a sentinel return address and runs `vm_until`, the same nested run an o3 call uses. the signature comes from the function's declared types, so a typed `o3` function is entered at its compiled region. the stack pointers are published by the gate store: a global in the interpreter, a store from the alloca in an llvm block, and in the jit the same two words (`S[1]`, `S[2]`) the exit stub writes. it passes under the interpreter, llvm with every block compiled (`ZYHOT=1`) and the arm64 jit under qemu (a dynamic binary: a static one has no `dlsym`). **not done.** a call from o3 code to an extern leaves the region like any call to ordinary code. lowering it to a direct call inside a region, so llvm could see the callee and its argument types, would need a variadic micro-op in the lifter, the optimizer, the rexec loop, the arm64 emitter and the llvm lowering, which today all assume at most two inputs. structs by value, more than 6 integer or 8 float arguments, and a callback that outlives its native call are not supported. **the default map is 1081344 words.** the genome (`rt.zc` plus `compiler.zc`) came to 134045 words, past the 131072 that the default map reserved. the default preset of `genmap` now reserves 0x28000 words for it and everything above moves up by 0x8000, with `memmap.h`, the const block in `rt.zc` and the javascript vm's constants following. the small maps are separate presets and did not change.