blob: b9a4bdede6b6db40009aefda2ac48d14a22ac9b4 [file] [log] [blame]
sewardj35421a32004-07-05 13:12:34 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
sewardjc0ee2ed2004-07-27 10:29:41 +00004/*--- This file (main/vex_main.c) is ---*/
sewardj35421a32004-07-05 13:12:34 +00005/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
7/*---------------------------------------------------------------*/
8
sewardj887a11a2004-07-05 17:26:47 +00009#include "libvex.h"
sewardjf13a16a2004-07-05 17:10:14 +000010
sewardjc0ee2ed2004-07-27 10:29:41 +000011#include "main/vex_globals.h"
12#include "main/vex_util.h"
13#include "host-generic/h_generic_regs.h"
14#include "host-x86/hdefs.h"
15#include "guest-x86/gdefs.h"
sewardjedf4d692004-08-17 13:52:58 +000016#include "ir/iropt.h"
sewardj35421a32004-07-05 13:12:34 +000017
18
19/* This file contains the top level interface to the library. */
20
21/* --------- Initialise the library. --------- */
22
23/* Exported to library client. */
24
sewardj887a11a2004-07-05 17:26:47 +000025void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000026 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000027 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000028 void (*failure_exit) ( void ),
29 /* logging output function */
30 void (*log_bytes) ( Char*, Int nbytes ),
31 /* debug paranoia level */
32 Int debuglevel,
sewardj58800ff2004-07-28 01:51:10 +000033 /* initial verbosity level */
sewardj35421a32004-07-05 13:12:34 +000034 Int verbosity,
35 /* Are we supporting valgrind checking? */
36 Bool valgrind_support,
37 /* Max # guest insns per bb */
38 Int guest_insns_per_bb
39)
40{
sewardjea602bc2004-10-14 21:40:12 +000041 /* First off, do enough minimal setup so that the follow asserts can
42 fail in a sane fashion, if need be. */
43 vex_failure_exit = failure_exit;
44 vex_log_bytes = log_bytes;
45
46 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +000047 vassert(!vex_initdone);
48 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +000049 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +000050 vassert(debuglevel >= 0);
sewardj35421a32004-07-05 13:12:34 +000051 vassert(verbosity >= 0);
sewardj35421a32004-07-05 13:12:34 +000052 vassert(guest_insns_per_bb >= 1 && guest_insns_per_bb <= 100);
sewardj443cd9d2004-07-18 23:06:45 +000053
sewardjea602bc2004-10-14 21:40:12 +000054 /* Check that Vex has been built with sizes of basic types as
55 stated in priv/libvex_basictypes.h. Failure of any of these is
56 a serious configuration error and should be corrected
57 immediately. If any of these assertions fail you can fully
58 expect Vex not to work properly, if at all. */
59
60 vassert(1 == sizeof(UChar));
61 vassert(1 == sizeof(Char));
62 vassert(2 == sizeof(UShort));
63 vassert(2 == sizeof(Short));
64 vassert(4 == sizeof(UInt));
65 vassert(4 == sizeof(Int));
66 vassert(8 == sizeof(ULong));
67 vassert(8 == sizeof(Long));
68 vassert(4 == sizeof(Float));
69 vassert(8 == sizeof(Double));
70 vassert(1 == sizeof(Bool));
71 vassert(4 == sizeof(Addr32));
72 vassert(8 == sizeof(Addr64));
73
74 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
75 vassert(sizeof(void*) == sizeof(int*));
76 vassert(sizeof(void*) == sizeof(HWord));
77
78 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +000079 vex_debuglevel = debuglevel;
80 vex_verbosity = verbosity;
81 vex_valgrind_support = valgrind_support;
sewardj35421a32004-07-05 13:12:34 +000082 vex_guest_insns_per_bb = guest_insns_per_bb;
sewardj443cd9d2004-07-18 23:06:45 +000083 vex_initdone = True;
84 LibVEX_SetAllocMode ( AllocModeTEMPORARY );
sewardj35421a32004-07-05 13:12:34 +000085}
86
87
88/* --------- Make a translation. --------- */
89
90/* Exported to library client. */
91
sewardj887a11a2004-07-05 17:26:47 +000092TranslateResult LibVEX_Translate (
sewardj35421a32004-07-05 13:12:34 +000093 /* The instruction sets we are translating from and to. */
94 InsnSet iset_guest,
95 InsnSet iset_host,
96 /* IN: the block to translate, and its guest address. */
sewardj81bd5502004-07-21 18:49:27 +000097 UChar* guest_bytes,
sewardj35421a32004-07-05 13:12:34 +000098 Addr64 guest_bytes_addr,
99 /* OUT: the number of bytes actually read */
100 Int* guest_bytes_read,
101 /* IN: a place to put the resulting code, and its size */
sewardj81bd5502004-07-21 18:49:27 +0000102 UChar* host_bytes,
103 Int host_bytes_size,
sewardj35421a32004-07-05 13:12:34 +0000104 /* OUT: how much of the output area is used. */
105 Int* host_bytes_used,
106 /* IN: optionally, an instrumentation function. */
sewardjf13a16a2004-07-05 17:10:14 +0000107 IRBB* (*instrument) ( IRBB* ),
sewardj35421a32004-07-05 13:12:34 +0000108 /* IN: optionally, an access check function for guest code. */
sewardj58800ff2004-07-28 01:51:10 +0000109 Bool (*byte_accessible) ( Addr64 ),
110 /* IN: if > 0, use this verbosity for this bb */
111 Int bb_verbosity
sewardj35421a32004-07-05 13:12:34 +0000112)
113{
sewardj81bd5502004-07-21 18:49:27 +0000114 /* This the bundle of functions we need to do the back-end stuff
115 (insn selection, reg-alloc, assembly) whilst being insulated
116 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000117 HReg* available_real_regs;
118 Int n_available_real_regs;
sewardj443cd9d2004-07-18 23:06:45 +0000119 Bool (*isMove) (HInstr*, HReg*, HReg*);
120 void (*getRegUsage) (HRegUsage*, HInstr*);
121 void (*mapRegs) (HRegRemap*, HInstr*);
122 HInstr* (*genSpill) ( HReg, Int );
123 HInstr* (*genReload) ( HReg, Int );
124 void (*ppInstr) ( HInstr* );
125 void (*ppReg) ( HReg );
sewardj36ca5132004-07-24 13:12:23 +0000126 HInstrArray* (*iselBB) ( IRBB*, Addr64(*)(Char*) );
sewardj443cd9d2004-07-18 23:06:45 +0000127 IRBB* (*bbToIR) ( UChar*, Addr64, Int*,
128 Bool(*)(Addr64), Bool );
sewardj81bd5502004-07-21 18:49:27 +0000129 Int (*emit) ( UChar*, Int, HInstr* );
sewardj36ca5132004-07-24 13:12:23 +0000130 Addr64 (*findHelper) ( Char* );
sewardj84ff0652004-08-23 16:16:08 +0000131 IRExpr* (*specHelper) ( Char*, IRExpr** );
sewardjf13a16a2004-07-05 17:10:14 +0000132
sewardjc9a65702004-07-07 16:32:57 +0000133 Bool host_is_bigendian = False;
sewardjf13a16a2004-07-05 17:10:14 +0000134 IRBB* irbb;
135 HInstrArray* vcode;
136 HInstrArray* rcode;
sewardj58800ff2004-07-28 01:51:10 +0000137 Int i, j, k, out_used, saved_verbosity;
sewardj2e56f9f2004-07-24 01:24:38 +0000138 UChar insn_bytes[32];
sewardjf13a16a2004-07-05 17:10:14 +0000139
sewardj36ca5132004-07-24 13:12:23 +0000140 available_real_regs = NULL;
141 n_available_real_regs = 0;
142 isMove = NULL;
143 getRegUsage = NULL;
144 mapRegs = NULL;
145 genSpill = NULL;
146 genReload = NULL;
147 ppInstr = NULL;
148 ppReg = NULL;
149 iselBB = NULL;
150 bbToIR = NULL;
151 emit = NULL;
152 findHelper = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000153 specHelper = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000154
sewardj58800ff2004-07-28 01:51:10 +0000155 saved_verbosity = vex_verbosity;
156 if (bb_verbosity > 0)
157 vex_verbosity = bb_verbosity;
158
sewardj35421a32004-07-05 13:12:34 +0000159 vassert(vex_initdone);
sewardj443cd9d2004-07-18 23:06:45 +0000160 LibVEX_ClearTemporary(False);
sewardjf13a16a2004-07-05 17:10:14 +0000161
162 /* First off, check that the guest and host insn sets
163 are supported. */
164 switch (iset_host) {
165 case InsnSetX86:
166 getAllocableRegs_X86 ( &n_available_real_regs,
167 &available_real_regs );
168 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
169 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_X86Instr;
170 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_X86Instr;
171 genSpill = (HInstr*(*)(HReg,Int)) genSpill_X86;
172 genReload = (HInstr*(*)(HReg,Int)) genReload_X86;
sewardj2b515872004-07-05 20:50:45 +0000173 ppInstr = (void(*)(HInstr*)) ppX86Instr;
174 ppReg = (void(*)(HReg)) ppHRegX86;
sewardjf13a16a2004-07-05 17:10:14 +0000175 iselBB = iselBB_X86;
sewardj81bd5502004-07-21 18:49:27 +0000176 emit = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
sewardjc9a65702004-07-07 16:32:57 +0000177 host_is_bigendian = False;
sewardjf13a16a2004-07-05 17:10:14 +0000178 break;
179 default:
sewardj887a11a2004-07-05 17:26:47 +0000180 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000181 }
182
183 switch (iset_guest) {
184 case InsnSetX86:
sewardj36ca5132004-07-24 13:12:23 +0000185 bbToIR = bbToIR_X86Instr;
186 findHelper = x86guest_findhelper;
sewardj84ff0652004-08-23 16:16:08 +0000187 specHelper = x86guest_spechelper;
sewardjf13a16a2004-07-05 17:10:14 +0000188 break;
189 default:
sewardj887a11a2004-07-05 17:26:47 +0000190 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000191 }
192
193 irbb = bbToIR ( guest_bytes,
194 guest_bytes_addr,
195 guest_bytes_read,
sewardjc9a65702004-07-07 16:32:57 +0000196 byte_accessible,
197 host_is_bigendian );
sewardjf13a16a2004-07-05 17:10:14 +0000198
199 if (irbb == NULL) {
200 /* Access failure. */
sewardj443cd9d2004-07-18 23:06:45 +0000201 LibVEX_ClearTemporary(False);
sewardj58800ff2004-07-28 01:51:10 +0000202 vex_verbosity = saved_verbosity;
sewardjf13a16a2004-07-05 17:10:14 +0000203 return TransAccessFail;
204 }
sewardjaa59f942004-10-09 09:34:36 +0000205
206 /* If debugging, show the raw guest bytes for this bb. */
207 if (vex_verbosity >= 2) {
208 UChar* p = guest_bytes;
209 vex_printf("\n");
210 vex_printf(". 0 %llx %d\n.", guest_bytes_addr, *guest_bytes_read );
211 for (i = 0; i < *guest_bytes_read; i++)
212 vex_printf(" %02x", (Int)p[i] );
213 vex_printf("\n");
214 }
215
216 /* Sanity check the initial IR. */
sewardj35439212004-07-14 22:36:10 +0000217 sanityCheckIRBB(irbb, Ity_I32);
sewardje8e9d732004-07-16 21:03:45 +0000218
sewardjedf4d692004-08-17 13:52:58 +0000219 /* Clean it up, hopefully a lot. */
sewardj695cff92004-10-13 14:50:14 +0000220 irbb = do_iropt_BB ( irbb, specHelper, guest_bytes_addr );
sewardjd7cb8532004-08-17 23:59:23 +0000221 sanityCheckIRBB(irbb, Ity_I32);
sewardjedf4d692004-08-17 13:52:58 +0000222
223 if (vex_verbosity > 0) {
224 vex_printf("\n-------- After IR optimisation --------\n");
225 ppIRBB ( irbb );
226 vex_printf("\n");
227 }
228
sewardjf13a16a2004-07-05 17:10:14 +0000229 /* Get the thing instrumented. */
230 if (instrument)
231 irbb = (*instrument)(irbb);
232
233 /* Turn it into virtual-registerised code. */
sewardj36ca5132004-07-24 13:12:23 +0000234 vcode = iselBB ( irbb, findHelper );
sewardjf13a16a2004-07-05 17:10:14 +0000235
sewardj1f40a0a2004-07-21 12:28:07 +0000236 if (vex_verbosity > 0) {
237 vex_printf("\n-------- Virtual registerised code --------\n");
238 for (i = 0; i < vcode->arr_used; i++) {
239 vex_printf("%3d ", i);
240 ppInstr(vcode->arr[i]);
241 vex_printf("\n");
242 }
sewardjfbcaf332004-07-08 01:46:01 +0000243 vex_printf("\n");
244 }
sewardjfbcaf332004-07-08 01:46:01 +0000245
sewardjf13a16a2004-07-05 17:10:14 +0000246 /* Register allocate. */
247 rcode = doRegisterAllocation ( vcode, available_real_regs,
248 n_available_real_regs,
249 isMove, getRegUsage, mapRegs,
sewardj2b515872004-07-05 20:50:45 +0000250 genSpill, genReload,
251 ppInstr, ppReg );
sewardjf13a16a2004-07-05 17:10:14 +0000252
sewardj1f40a0a2004-07-21 12:28:07 +0000253 if (vex_verbosity > 0) {
254 vex_printf("\n-------- Post-regalloc code --------\n");
255 for (i = 0; i < rcode->arr_used; i++) {
256 vex_printf("%3d ", i);
257 ppInstr(rcode->arr[i]);
258 vex_printf("\n");
259 }
sewardjfbcaf332004-07-08 01:46:01 +0000260 vex_printf("\n");
261 }
sewardjfbcaf332004-07-08 01:46:01 +0000262
sewardj81bd5502004-07-21 18:49:27 +0000263 /* Assemble */
sewardj81bd5502004-07-21 18:49:27 +0000264 out_used = 0; /* tracks along the host_bytes array */
265 for (i = 0; i < rcode->arr_used; i++) {
sewardj14731f22004-07-25 01:24:28 +0000266 if (vex_verbosity > 1) {
sewardjbad34a92004-07-22 01:14:11 +0000267 ppInstr(rcode->arr[i]);
268 vex_printf("\n");
269 }
sewardj81bd5502004-07-21 18:49:27 +0000270 j = (*emit)( insn_bytes, 32, rcode->arr[i] );
sewardj14731f22004-07-25 01:24:28 +0000271 if (vex_verbosity > 1) {
sewardjbad34a92004-07-22 01:14:11 +0000272 for (k = 0; k < j; k++)
sewardj86898e82004-07-22 17:26:12 +0000273 if (insn_bytes[k] < 16)
274 vex_printf("0%x ", (UInt)insn_bytes[k]);
275 else
276 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000277 vex_printf("\n\n");
278 }
sewardj81bd5502004-07-21 18:49:27 +0000279 if (out_used + j > host_bytes_size) {
280 LibVEX_ClearTemporary(False);
sewardj58800ff2004-07-28 01:51:10 +0000281 vex_verbosity = saved_verbosity;
sewardj81bd5502004-07-21 18:49:27 +0000282 return TransOutputFull;
283 }
284 for (k = 0; k < j; k++) {
285 host_bytes[out_used] = insn_bytes[k];
286 out_used++;
287 }
288 vassert(out_used <= host_bytes_size);
289 }
290 *host_bytes_used = out_used;
291
sewardj1f40a0a2004-07-21 12:28:07 +0000292 // LibVEX_ClearTemporary(True);
293 LibVEX_ClearTemporary(False);
sewardjf13a16a2004-07-05 17:10:14 +0000294
sewardj58800ff2004-07-28 01:51:10 +0000295 vex_verbosity = saved_verbosity;
sewardj35421a32004-07-05 13:12:34 +0000296 return TransOK;
297}
298
299
300
301/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000302/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000303/*---------------------------------------------------------------*/