Relying on JS function calls and variable declarations is actually more efficient in this case since the underlying JS JIT can perform a lot of optimizations (SSA / Register Allocation). We do stack allocation for structs and local variables for which you need to take the addresses of.
The "let" keyword is left in there because we wanted to stay compatible with JS. So any JS program is also an LLJS program. This way it would be easy to integrate into an existing code base. As for the "let" vs. "var" debate, we chose "let" because of its block scoping semantics and because we didn't want to let variable declarations alias each other with different types.