20
20
#define ADR_IMM (1<<20) // signed imm21
21
21
#define ADRP_IMM (1LL<<32) // signed imm21 * 4096
22
22
23
- static bool aarch64_may_use_b(ir_ctx *ctx , const void *addr)
23
+ static bool aarch64_may_use_b(ir_code_buffer *code_buffer , const void *addr)
24
24
{
25
- if (ctx-> code_buffer) {
26
- if (addr >= ctx-> code_buffer->start && (char*)addr < (char*)ctx-> code_buffer->end) {
27
- return (((char*)ctx-> code_buffer->end - (char*)ctx-> code_buffer->start) < B_IMM);
28
- } else if ((char*)addr >= (char*)ctx-> code_buffer->end) {
29
- return (((char*)addr - (char*)ctx-> code_buffer->start) < B_IMM);
30
- } else if (addr < ctx-> code_buffer->start) {
31
- return (((char*)ctx-> code_buffer->end - (char*)addr) < B_IMM);
25
+ if (code_buffer) {
26
+ if (addr >= code_buffer->start && (char*)addr < (char*)code_buffer->end) {
27
+ return (((char*)code_buffer->end - (char*)code_buffer->start) < B_IMM);
28
+ } else if ((char*)addr >= (char*)code_buffer->end) {
29
+ return (((char*)addr - (char*)code_buffer->start) < B_IMM);
30
+ } else if (addr < code_buffer->start) {
31
+ return (((char*)code_buffer->end - (char*)addr) < B_IMM);
32
32
}
33
33
}
34
- return 1; //???
34
+ return 0;
35
35
}
36
36
37
37
#if 0
38
- static bool aarch64_may_use_adr(ir_ctx *ctx , const void *addr)
38
+ static bool aarch64_may_use_adr(ir_code_buffer *code_buffer , const void *addr)
39
39
{
40
- if (ctx-> code_buffer) {
41
- if (addr >= ctx-> code_buffer->start && (char*)addr < (char*)ctx-> code_buffer->end) {
42
- return (((char*)ctx-> code_buffer->end - (char*)ctx-> code_buffer->start) < ADR_IMM);
43
- } else if ((char*)addr >= (char*)ctx-> code_buffer->end) {
44
- return (((char*)addr - (char*)ctx-> code_buffer->start) < ADR_IMM);
45
- } else if (addr < ctx-> code_buffer->start) {
46
- return (((char*)ctx-> code_buffer->end - (char*)addr) < ADR_IMM);
40
+ if (code_buffer) {
41
+ if (addr >= code_buffer->start && (char*)addr < (char*)code_buffer->end) {
42
+ return (((char*)code_buffer->end - (char*)code_buffer->start) < ADR_IMM);
43
+ } else if ((char*)addr >= (char*)code_buffer->end) {
44
+ return (((char*)addr - (char*)code_buffer->start) < ADR_IMM);
45
+ } else if (addr < code_buffer->start) {
46
+ return (((char*)code_buffer->end - (char*)addr) < ADR_IMM);
47
47
}
48
48
}
49
49
return 0;
50
50
}
51
51
52
- static bool aarch64_may_use_adrp(ir_ctx *ctx , const void *addr)
52
+ static bool aarch64_may_use_adrp(ir_code_buffer *code_buffer , const void *addr)
53
53
{
54
- if (ctx-> code_buffer) {
55
- if (addr >= ctx-> code_buffer->start && (char*)addr < (char*)ctx-> code_buffer->end) {
56
- return (((char*)ctx-> code_buffer->end - (char*)ctx-> code_buffer->start) < ADRP_IMM);
57
- } else if ((char*)addr >= (char*)ctx-> code_buffer->end) {
58
- return (((char*)addr - (char*)ctx-> code_buffer->start) < ADRP_IMM);
59
- } else if (addr < ctx-> code_buffer->start) {
60
- return (((char*)ctx-> code_buffer->end - (char*)addr) < ADRP_IMM);
54
+ if (code_buffer) {
55
+ if (addr >= code_buffer->start && (char*)addr < (char*)code_buffer->end) {
56
+ return (((char*)code_buffer->end - (char*)code_buffer->start) < ADRP_IMM);
57
+ } else if ((char*)addr >= (char*)code_buffer->end) {
58
+ return (((char*)addr - (char*)code_buffer->start) < ADRP_IMM);
59
+ } else if (addr < code_buffer->start) {
60
+ return (((char*)code_buffer->end - (char*)addr) < ADRP_IMM);
61
61
}
62
62
}
63
63
return 0;
@@ -1176,9 +1176,10 @@ static void ir_emit_load(ir_ctx *ctx, ir_type type, ir_reg reg, ir_ref src)
1176
1176
ir_insn *insn = &ctx->ir_base[src];
1177
1177
1178
1178
if (insn->op == IR_SYM || insn->op == IR_FUNC) {
1179
+ const char *name = ir_get_str(ctx, insn->val.name);
1179
1180
void *addr = (ctx->loader && ctx->loader->resolve_sym_name) ?
1180
- ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx , insn->val.name) ) :
1181
- ir_resolve_sym_name(ir_get_str(ctx, insn->val. name) );
1181
+ ctx->loader->resolve_sym_name(ctx->loader, name , insn->op == IR_FUNC ) :
1182
+ ir_resolve_sym_name(name);
1182
1183
IR_ASSERT(addr);
1183
1184
ir_emit_load_imm_int(ctx, type, reg, (intptr_t)addr);
1184
1185
} else if (insn->op == IR_STR) {
@@ -4360,7 +4361,7 @@ static void ir_emit_call_ex(ir_ctx *ctx, ir_ref def, ir_insn *insn, int32_t used
4360
4361
if (IR_IS_CONST_REF(insn->op2)) {
4361
4362
void *addr = ir_call_addr(ctx, insn, &ctx->ir_base[insn->op2]);
4362
4363
4363
- if (aarch64_may_use_b(ctx, addr)) {
4364
+ if (aarch64_may_use_b(ctx->code_buffer , addr)) {
4364
4365
| bl &addr
4365
4366
} else {
4366
4367
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, (intptr_t)addr);
@@ -4435,7 +4436,7 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn)
4435
4436
if (IR_IS_CONST_REF(insn->op2)) {
4436
4437
void *addr = ir_call_addr(ctx, insn, &ctx->ir_base[insn->op2]);
4437
4438
4438
- if (aarch64_may_use_b(ctx, addr)) {
4439
+ if (aarch64_may_use_b(ctx->code_buffer , addr)) {
4439
4440
| b &addr
4440
4441
} else {
4441
4442
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, (intptr_t)addr);
@@ -4468,7 +4469,7 @@ static void ir_emit_ijmp(ir_ctx *ctx, ir_ref def, ir_insn *insn)
4468
4469
} else if (IR_IS_CONST_REF(insn->op2)) {
4469
4470
void *addr = ir_jmp_addr(ctx, insn, &ctx->ir_base[insn->op2]);
4470
4471
4471
- if (aarch64_may_use_b(ctx, addr)) {
4472
+ if (aarch64_may_use_b(ctx->code_buffer , addr)) {
4472
4473
| b &addr
4473
4474
} else {
4474
4475
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, (intptr_t)addr);
@@ -4494,7 +4495,7 @@ static void ir_emit_guard(ir_ctx *ctx, ir_ref def, ir_insn *insn)
4494
4495
if (IR_IS_CONST_REF(insn->op3)) {
4495
4496
void *addr = ir_jmp_addr(ctx, insn, &ctx->ir_base[insn->op3]);
4496
4497
4497
- if (aarch64_may_use_b(ctx, addr)) {
4498
+ if (aarch64_may_use_b(ctx->code_buffer , addr)) {
4498
4499
| b &addr
4499
4500
} else {
4500
4501
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, (intptr_t)addr);
@@ -4654,7 +4655,7 @@ static void ir_emit_guard_cmp_int(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *
4654
4655
if (IR_IS_CONST_REF(op2) && ctx->ir_base[op2].val.u64 == 0) {
4655
4656
if (op == IR_ULT) {
4656
4657
/* always false */
4657
- if (aarch64_may_use_b(ctx, addr)) {
4658
+ if (aarch64_may_use_b(ctx->code_buffer , addr)) {
4658
4659
| b &addr
4659
4660
} else {
4660
4661
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, (intptr_t)addr);
@@ -4807,7 +4808,7 @@ static void ir_emit_exitcall(ir_ctx *ctx, ir_ref def, ir_insn *insn)
4807
4808
if (IR_IS_CONST_REF(insn->op2)) {
4808
4809
void *addr = ir_call_addr(ctx, insn, &ctx->ir_base[insn->op2]);
4809
4810
4810
- if (aarch64_may_use_b(ctx, addr)) {
4811
+ if (aarch64_may_use_b(ctx->code_buffer , addr)) {
4811
4812
| bl &addr
4812
4813
} else {
4813
4814
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, (intptr_t)addr);
@@ -5835,17 +5836,8 @@ const void *ir_emit_exitgroup(uint32_t first_exit_point, uint32_t exit_points_pe
5835
5836
dasm_State **Dst, *dasm_state;
5836
5837
int ret;
5837
5838
5838
- /* IR_ASSERT(aarch64_may_use_b(ctx, exit_addr)) */
5839
5839
IR_ASSERT(code_buffer);
5840
- if ((char*)exit_addr >= (char*)code_buffer->start && (char*)exit_addr < (char*)code_buffer->end) {
5841
- IR_ASSERT(((char*)code_buffer->end - (char*)code_buffer->end) < B_IMM);
5842
- } else if ((char*)exit_addr >= (char*)code_buffer->end) {
5843
- IR_ASSERT(((char*)exit_addr - (char*)code_buffer->start) < B_IMM);
5844
- } else if ((char*)exit_addr < (char*)code_buffer->start) {
5845
- IR_ASSERT(((char*)code_buffer->end - (char*)exit_addr) < B_IMM);
5846
- } else {
5847
- IR_ASSERT(0);
5848
- }
5840
+ IR_ASSERT(aarch64_may_use_b(code_buffer, exit_addr));
5849
5841
5850
5842
Dst = &dasm_state;
5851
5843
dasm_state = NULL;
@@ -6010,3 +6002,73 @@ static int ir_add_veneer(dasm_State *Dst, void *buffer, uint32_t ins, int *b, ui
6010
6002
6011
6003
return n;
6012
6004
}
6005
+
6006
+ bool ir_needs_thunk(ir_code_buffer *code_buffer, void *addr)
6007
+ {
6008
+ return !aarch64_may_use_b(code_buffer, addr);
6009
+ }
6010
+
6011
+ void *ir_emit_thunk(ir_code_buffer *code_buffer, void *addr, size_t *size_ptr)
6012
+ {
6013
+ void *entry;
6014
+ size_t size;
6015
+ dasm_State **Dst, *dasm_state;
6016
+ int ret;
6017
+
6018
+ Dst = &dasm_state;
6019
+ dasm_state = NULL;
6020
+ dasm_init(&dasm_state, DASM_MAXSECTION);
6021
+ dasm_setupglobal(&dasm_state, dasm_labels, ir_lb_MAX);
6022
+ dasm_setup(&dasm_state, dasm_actions);
6023
+
6024
+ |.code
6025
+ | movz Rx(IR_REG_INT_TMP), #((uint64_t)(addr) & 0xffff)
6026
+ | movk Rx(IR_REG_INT_TMP), #(((uint64_t)(addr) >> 16) & 0xffff), lsl #16
6027
+ | movk Rx(IR_REG_INT_TMP), #(((uint64_t)(addr) >> 32) & 0xffff), lsl #32
6028
+ | movk Rx(IR_REG_INT_TMP), #(((uint64_t)(addr) >> 48) & 0xffff), lsl #48
6029
+ | br Rx(IR_REG_INT_TMP)
6030
+
6031
+ ret = dasm_link(&dasm_state, &size);
6032
+ if (ret != DASM_S_OK) {
6033
+ IR_ASSERT(0);
6034
+ dasm_free(&dasm_state);
6035
+ return NULL;
6036
+ }
6037
+
6038
+ if (size > (size_t)((char*)code_buffer->end - (char*)code_buffer->pos)) {
6039
+ dasm_free(&dasm_state);
6040
+ return NULL;
6041
+ }
6042
+
6043
+ entry = code_buffer->pos;
6044
+ ret = dasm_encode(&dasm_state, entry);
6045
+ if (ret != DASM_S_OK) {
6046
+ dasm_free(&dasm_state);
6047
+ return NULL;
6048
+ }
6049
+
6050
+ *size_ptr = size;
6051
+ code_buffer->pos = (char*)code_buffer->pos + size;
6052
+
6053
+ dasm_free(&dasm_state);
6054
+ ir_mem_flush(entry, size);
6055
+
6056
+ return entry;
6057
+ }
6058
+
6059
+ void ir_fix_thunk(void *thunk_entry, void *addr)
6060
+ {
6061
+ uint32_t *code = thunk_entry;
6062
+ IR_ASSERT((code[0] & 0xffe00000) == 0xd2800000
6063
+ && (code[1] & 0xffe00000) == 0xf2a00000
6064
+ && (code[2] & 0xffe00000) == 0xf2c00000
6065
+ && (code[3] & 0xffe00000) == 0xf2e00000
6066
+ && (code[4] & 0xfffffc1f) == 0xd61f0000);
6067
+
6068
+ code[0] = (code[0] & 0xffe0001f) | (uint32_t)((uint64_t)(addr) & 0xffff) << 5;
6069
+ code[1] = (code[1] & 0xffe0001f) | (uint32_t)(((uint64_t)(addr) >> 16) & 0xffff) << 5;
6070
+ code[2] = (code[2] & 0xffe0001f) | (uint32_t)(((uint64_t)(addr) >> 32) & 0xffff) << 5;
6071
+ code[3] = (code[3] & 0xffe0001f) | (uint32_t)(((uint64_t)(addr) >> 48) & 0xffff) << 5;
6072
+
6073
+ ir_mem_flush(code, sizeof(uint32_t) * 4);
6074
+ }
0 commit comments