Implementation is mostly shared with __builtin_frame_address. It seems to work on arm64, i386 and x86_64. It may need to be adapted for other targets.
Unified · Split
| @@ -3874,13 +3874,18 @@ ST_FUNC void unary(void) · 3873 unmodified lines | ||
| 3874 | 3874 | } |
| 3875 | 3875 | break; |
| 3876 | 3876 | case TOK_builtin_frame_address: |
| 3877 | + case TOK_builtin_return_address: | |
| 3877 | 3878 | { |
| 3879 | + int tok1 = tok; | |
| 3878 | 3880 | int level; |
| 3879 | 3881 | CType type; |
| 3880 | 3882 | next(); |
| 3881 | 3883 | skip('('); |
| 3882 | 3884 | if (tok != TOK_CINT || tokc.i < 0) { |
| 3883 | − tcc_error("__builtin_frame_address only takes positive integers"); | |
| 3885 | + tcc_error("%s only takes positive integers", | |
| 3886 | + tok1 == TOK_builtin_return_address ? | |
| 3887 | + "__builtin_return_address" : | |
| 3888 | + "__builtin_frame_address"); | |
| 3884 | 3889 | } |
| 3885 | 3890 | level = tokc.i; |
| 3886 | 3891 | next(); |
| @@ -3892,6 +3897,13 @@ ST_FUNC void unary(void) · 5 unmodified lines | ||
| 3892 | 3897 | mk_pointer(&vtop->type); |
| 3893 | 3898 | indir(); /* -> parent frame */ |
| 3894 | 3899 | } |
| 3900 | + if (tok1 == TOK_builtin_return_address) { | |
| 3901 | + // assume return address is just above frame pointer on stack | |
| 3902 | + vpushi(PTR_SIZE); | |
| 3903 | + gen_op('+'); | |
| 3904 | + mk_pointer(&vtop->type); | |
| 3905 | + indir(); | |
| 3906 | + } | |
| 3895 | 3907 | } |
| 3896 | 3908 | break; |
| 3897 | 3909 | #ifdef TCC_TARGET_X86_64 |
| @@ -130,6 +130,7 @@ · 129 unmodified lines | ||
| 130 | 130 | DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p") |
| 131 | 131 | DEF(TOK_builtin_constant_p, "__builtin_constant_p") |
| 132 | 132 | DEF(TOK_builtin_frame_address, "__builtin_frame_address") |
| 133 | + DEF(TOK_builtin_return_address, "__builtin_return_address") | |
| 133 | 134 | #ifdef TCC_TARGET_X86_64 |
| 134 | 135 | #ifdef TCC_TARGET_PE |
| 135 | 136 | DEF(TOK_builtin_va_start, "__builtin_va_start") |