# emit_addr.ludic — addresses of lvalues (struct fields and slice elements), # shared by expression loads and assignment stores. Each returns the address # register; the element/field type is written into g_addr_ty. var g_addr_ty: pointer # out-param: the type at the computed address # address of `base.field` function emit_member_addr(e: Node) -> pointer { let base = emit_expr(e.a) let s = layout_node(base.ty) if (s == null) { perr(`member access on non-aggregate {base.ty}`) } let fidx = field_index(s, e.s) if fidx < 0 { perr(`no such field {e.s}`) } g_addr_ty = field_type(s, e.s) let r = nreg() emit(" "); emit(r); emit(" = getelementptr inbounds "); emit(layout_ty(base.ty)) emit(", ptr "); emit(base.code); emit(", i32 0, i32 "); emit(itoa(fidx)); emit("\n") return r } # address of `base[index]` (slices only in this subset) function emit_index_addr(e: Node) -> pointer { let base = emit_expr(e.a) if not is_slice_ty(base.ty) { # a raw pointer: address of element i let bi = emit_expr(e.b) # (evaluate index first — it may set g_addr_ty) if (base.ty == "words") { # a `words` buffer: 32-bit int elements let rw = emit_bind(`getelementptr inbounds i32, ptr {base.code}, i32 {bi.code}`) g_addr_ty = "int" return rw } if (base.ty == "fixeds") { # a `fixeds` buffer: 32-bit fixed elements let rf = emit_bind(`getelementptr inbounds i32, ptr {base.code}, i32 {bi.code}`) g_addr_ty = "fixed" return rf } if (base.ty == "pointers") { # a `pointers` buffer: pointer elements let rp = emit_bind(`getelementptr inbounds ptr, ptr {base.code}, i32 {bi.code}`) g_addr_ty = "ptr" return rp } let r = emit_bind(`getelementptr inbounds i8, ptr {base.code}, i32 {bi.code}`) # a ptr/str: bytes g_addr_ty = "byte" # set last so the caller sees it return r } let el = slice_elem(base.ty) # load the data pointer from the slice header (field 0) let dp = nreg() emit(" "); emit(dp); emit(" = getelementptr inbounds %LSlice, ptr ") emit(base.code); emit(", i32 0, i32 0\n") let data = nreg() emit(" "); emit(data); emit(" = load ptr, ptr "); emit(dp); emit("\n") let ix = emit_expr(e.b) # (evaluate index BEFORE setting let r = nreg() # g_addr_ty — a member-access index emit(" "); emit(r); emit(" = getelementptr inbounds "); emit(llty(el)) # overwrites it) emit(", ptr "); emit(data); emit(", i32 "); emit(ix.code); emit("\n") g_addr_ty = el # set last so the caller sees the element type return r }