# UCE real generated unit -> WASM PIC side module report

Remote host: `k-uce`  
Working directory/artifacts left in place: `/tmp/uce/wasm-phase0/realunit/`  
Repository `/Code/uce.openfu.com/uce` was treated read-only; patched copies/shims only under `/tmp/uce/wasm-phase0/realunit/`.

## Result

Both real generated units compiled and linked as WASM PIC side modules with `dylink.0`:

- `collections.uce.cpp` -> `/tmp/uce/wasm-phase0/realunit/collections.wasm`
  - `dylink.0`: `memsize=1208 memalign=2^2 tablesize=3 tablealign=2^0`
  - imports: 52
  - exports: 23
  - allocator status: no exported/defined `malloc`, `free`, or `operator new`; `operator new`/sized delete are imports (`env._Znwm`, `env._ZdlPvm`).
- `hello.uce.cpp` -> `/tmp/uce/wasm-phase0/realunit/hello.wasm`
  - `dylink.0`: `memsize=5544 memalign=2^2 tablesize=0 tablealign=2^0`
  - imports: 38
  - exports: 24
  - allocator status: no exported/defined `malloc`, `free`, or `operator new`; `operator new`/sized delete are imports (`env._Znwm`, `env._ZdlPvm`).

Inspector outputs are saved remotely as:

- `/tmp/uce/wasm-phase0/realunit/collections.inspect.txt`
- `/tmp/uce/wasm-phase0/realunit/hello.inspect.txt`

## Final command lines

Run on `k-uce` from `/tmp/uce/wasm-phase0/realunit`.

`collections`:

```sh
/opt/wasi-sdk/bin/clang++ --target=wasm32-wasip1 -fPIC -fvisibility=default -O1 -fno-exceptions \
  -I/tmp/uce/wasm-phase0/realunit/shim -I/Code/uce.openfu.com/uce/src/lib \
  -c collections.uce.cpp -o collections.o

/opt/wasi-sdk/bin/wasm-ld -shared --experimental-pic --unresolved-symbols=import-dynamic \
  collections.o -o collections.wasm --export=__uce_render

python3 /Code/uce.openfu.com/uce/spikes/wasm-phase0/wasm_inspect.py collections.wasm
```

`hello`:

```sh
/opt/wasi-sdk/bin/clang++ --target=wasm32-wasip1 -fPIC -fvisibility=default -O1 -fno-exceptions \
  -I/tmp/uce/wasm-phase0/realunit/shim -I/Code/uce.openfu.com/uce/src/lib \
  -c hello.uce.cpp -o hello.o

/opt/wasi-sdk/bin/wasm-ld -shared --experimental-pic --unresolved-symbols=import-dynamic \
  hello.o -o hello.wasm --export=__uce_render
```

Note: the stub-spike command exported `uce_unit_render`, but these generated units define/export `__uce_render` from the repo `RENDER` macro, so the real-unit link exports `__uce_render`.

## Ordered friction points and fixes

1. **WASI sysroot rejects `<signal.h>` by default.**

   First compile failed via `/Code/uce.openfu.com/uce/src/lib/sys.h`:

   ```txt
   /share/wasi-sysroot/include/wasm32-wasip1/signal.h:2:2: error:
   "wasm lacks signal support; to enable minimal signal emulation, compile with -D_WASI_EMULATED_SIGNAL ..."
   ```

   Fix: added `/tmp/uce/wasm-phase0/realunit/shim/signal.h` before repo/system includes. Key lines:

   ```c
   typedef int sig_atomic_t;
   typedef void (*sighandler_t)(int);
   #define SIGTERM 15
   int raise(int);
   sighandler_t signal(int, sighandler_t);
   ```

   This is only enough for declarations in `sys.h`; real signal behavior has no WASI equivalent.

2. **Generated `collections.uce.cpp` includes missing local `demo_guard.h`.**

   First compile also failed:

   ```txt
   fatal error: 'demo_guard.h' file not found
   ```

   Fix: added empty include guard shim `/tmp/uce/wasm-phase0/realunit/shim/demo_guard.h`:

   ```c
   #ifndef UCE_WASM_SHIM_DEMO_GUARD_H
   #define UCE_WASM_SHIM_DEMO_GUARD_H
   #endif
   ```

3. **Generated source uses an absolute repo include, preventing header interposition.**

   Original generated line:

   ```c++
   #include "/Code/uce.openfu.com/uce/src/lib/uce_lib.h"
   ```

   To use patched shim headers without touching `/Code`, copied the generated units into the workdir and changed only that line to:

   ```c++
   #include "uce_lib.h"
   ```

   Copies are `/tmp/uce/wasm-phase0/realunit/collections.uce.cpp` and `hello.uce.cpp`.

4. **`types.h` defines global `operator new/delete` in every unit.**

   A straight build linked, but exported allocator definitions (`_Znwm`, `_ZdlPv`), violating the side-module allocator rule. The repo code in `types.h` contains:

   ```c++
   void * operator new(decltype(sizeof(0)) n) noexcept(false) { ... malloc(n) ... }
   void operator delete(void * p) throw() { free(p); }
   ```

   Fix: copied `uce_lib.h` and `types.h` to the shim tree, then patched only the copied `shim/types.h` allocator block to declarations:

   ```c++
   // WASM side-module shim: allocator must be provided by the host/core module,
   // not defined in each generated unit. Keep declarations only.
   void * operator new(decltype(sizeof(0)) n) noexcept(false);
   void operator delete(void * p) throw();
   ```

   Verification from `llvm-nm -C collections.o`:

   ```txt
            U operator delete(void*, unsigned long)
            U operator new(unsigned long)
   ```

## Notable imports / GOT entries

`collections.wasm` notable imports:

- allocator/runtime: `env._Znwm`, `env._ZdlPvm`, libc++ string/iostream helpers, `env.__stack_pointer`, `env.memory`, `env.__indirect_function_table`
- UCE/runtime functions: `DValue::set`, `DValue::operator[]`, `DValue::push`, `dv_filter`, `dv_map`, `dv_group_by`, `list_unique`, `list_sort`, `replace`, `to_upper`, `html_escape`, `json_encode`, `var_dump`, `time`
- MySQL wrappers are imported even for this unit because included header inline functions reference `MySQL` methods.
- GOT.mem globals:
  - `GOT.mem.context`
  - `GOT.mem._ZNSt3__25ctypeIcE2idE`
  - `GOT.mem._ZTVN10__cxxabiv117__class_type_infoE`

`hello.wasm` notable imports:

- allocator/runtime: `env._Znwm`, `env._ZdlPvm`, libc++ string/iostream helpers, `env.memcmp`
- UCE/runtime functions: `time`, `html_escape`, `html_escapey`, `var_dump`
- GOT.mem globals:
  - `GOT.mem.context`
  - `GOT.mem._ZNSt3__219piecewise_constructE`
  - `GOT.mem._ZNSt3__25ctypeIcE2idE`

## Phase 2 land mines

- `src/lib/sys.h` includes `<signal.h>` and declares signals/tasks/socket/process/file-lock APIs. WASI has no normal POSIX signals, fork/exec, traditional sockets, or process model. These need real repo-level `#ifdef __wasm__` / runtime boundary design, not local shims.
- `types.h` defines global allocator operators in a header. For side modules this must move to the core/runtime or be gated out under WASM side-module builds; otherwise each unit defines its own allocator entry points.
- Generated units include `/Code/.../uce_lib.h` by absolute path. That makes cross-target header selection brittle. The generator should emit a logical include (`"uce_lib.h"`) and the build should supply target-specific include order.
- Header-defined helper functions cause many exports from each unit (`to_string`, MySQL wrapper functions, vector slow-path/lambda helpers, globals `parent_pid`, `my_pid`, `context`). For a clean side-module ABI, these should probably be hidden, moved out of headers, marked inline/static where appropriate, or provided by the core module.
- MySQL inline wrappers are pulled into every unit by `uce_lib.h` even when the unit does not use MySQL directly. This is why `MySQL::connect/disconnect/query/error` imports appear in both outputs.
- Kept `-fno-exceptions`; no try/catch blocker was hit for these two generated units.
