058-fnptr-tab.scm (1755B)
1 ;; tests/cc-cg/58-fnptr-tab.scm — array of function pointers initialized 2 ;; with named functions. §L.3. 3 ;; 4 ;; Models: 5 ;; int f1(void) { return 1; } 6 ;; int f2(void) { return 2; } 7 ;; int (*tab[])(void) = { f1, f2 }; 8 ;; int main(void) { return tab[0]() + tab[1]() * 10; } (== 21) 9 ;; 10 ;; tab[i] is read via &tab + i (in fn-ptr units == 8 bytes), then a 11 ;; %callr indirect call. 12 13 (let* ((cg (cg-init)) 14 (fnty (%ctype 'fn -1 -1 (list %t-i32 '() #f))) 15 (fnptr (%ctype 'ptr 8 8 fnty))) 16 ;; int f1(void) { return 1; } 17 (cg-fn-begin cg "f1" '() %t-i32) 18 (cg-push-imm cg %t-i32 1) 19 (cg-return cg) 20 (cg-fn-end cg) 21 ;; int f2(void) { return 2; } 22 (cg-fn-begin cg "f2" '() %t-i32) 23 (cg-push-imm cg %t-i32 2) 24 (cg-return cg) 25 (cg-fn-end cg) 26 ;; tab[2] = { &f1, &f2 } — two label-ref pieces. 27 (let* ((aty (%ctype 'arr 16 8 (cons fnptr 2))) 28 (tab (%sym "tab" 'var 'static aty #f))) 29 (cg-emit-global cg tab (list (cons 'label-ref "f1") 30 (cons 'label-ref "f2"))) 31 ;; int main(void) { return tab[0]() + tab[1]() * 10; } 32 (cg-fn-begin cg "main" '() %t-i32) 33 (let ((pp (%ctype 'ptr 8 8 fnptr)) ; ptr to fnptr = pointee size 8 34 (emit-call 35 (lambda (idx ppt) 36 (cg-push-sym cg tab) (cg-take-addr cg) 37 (cg-cast cg ppt) ; relabel to ptr-to-fnptr 38 (cg-push-imm cg %t-i32 idx) 39 (cg-binop cg 'add) ; ptr arith scales by 8 40 (cg-push-deref cg) (cg-load cg) 41 (cg-call cg 0 #t)))) 42 (emit-call 0 pp) 43 (emit-call 1 pp) 44 (cg-push-imm cg %t-i32 10) 45 (cg-binop cg 'mul) 46 (cg-binop cg 'add)) 47 (cg-return cg) 48 (cg-fn-end cg)) 49 (write-bv-fd 1 (cg-finish cg)))