@@ -91,6 +91,7 @@ let trans_visitor
91
91
let imm (i :int64 ) : Il.operand = imm_of_ty i word_ty_mach in
92
92
let simm (i :int64 ) : Il.operand = imm_of_ty i word_ty_signed_mach in
93
93
let one = imm 1L in
94
+ let neg_one = simm (- 1L ) in
94
95
let zero = imm 0L in
95
96
let imm_true = imm_of_ty 1L TY_u8 in
96
97
let imm_false = imm_of_ty 0L TY_u8 in
@@ -1858,7 +1859,38 @@ let trans_visitor
1858
1859
in
1859
1860
get_typed_mem_glue g fty inner
1860
1861
1861
- and get_cmp_glue _ = failwith " TODO"
1862
+ and get_cmp_glue ty =
1863
+ let arg_ty_params_alias = 0 in
1864
+ let arg_lhs_alias = 1 in
1865
+ let arg_rhs_alias = 2 in
1866
+ let g = GLUE_cmp ty in
1867
+ let inner (out_ptr :Il.cell ) (args :Il.cell ) =
1868
+ let dst = deref out_ptr in
1869
+ let ty_params = deref (get_element_ptr args arg_ty_params_alias) in
1870
+ let lhs = deref (get_element_ptr args arg_lhs_alias) in
1871
+ let rhs = deref (get_element_ptr args arg_rhs_alias) in
1872
+ let early_finish_jmps = Queue. create () in
1873
+ let cmp_part lhs rhs ty =
1874
+ let tmp = trans_cmp ~ty_params ~ty (Il. Cell lhs) (Il. Cell rhs) in
1875
+ let keep_going_jmps =
1876
+ trans_compare_simple Il. JE tmp zero
1877
+ in
1878
+ mov dst tmp;
1879
+ Queue. add (mark() ) early_finish_jmps;
1880
+ emit (Il. jmp Il. JMP Il. CodeNone );
1881
+ List. iter patch keep_going_jmps
1882
+ in
1883
+ mov dst zero;
1884
+ iter_ty_parts_full ty_params lhs rhs ty cmp_part;
1885
+ Queue. iter patch early_finish_jmps;
1886
+ in
1887
+ let ty_params_ptr = ty_params_covering ty in
1888
+ let fty =
1889
+ mk_ty_fn
1890
+ (local_slot Ast. TY_int )
1891
+ [| ty_params_ptr; alias_slot ty; alias_slot ty |]
1892
+ in
1893
+ get_typed_mem_glue g fty inner
1862
1894
1863
1895
(*
1864
1896
* Vector-growth glue takes four arguments:
@@ -2108,62 +2140,120 @@ let trans_visitor
2108
2140
(Array. append [| ty_params_ptr |] args)
2109
2141
clo
2110
2142
2111
- (* [trans_compare_full] returns the quad number of the cjmp, which the
2112
- * caller patches to the cjmp destination.
2143
+ (*
2144
+ * NB: there are 2 categories of comparisons:
2145
+ *
2146
+ * - Those called 'compare' that take a jmpop and return a jump list
2147
+ * that the caller should patch.
2148
+ *
2149
+ * - Those called 'cmp' that return a number, -1/0/1, indicating the
2150
+ * relative order of lhs and rhs.
2151
+ *
2152
+ * While in theory compare could be built out of cmp, on real machines
2153
+ * we are forced to build cmp out of compare.
2154
+ *)
2155
+
2156
+
2157
+ (*
2158
+ * [trans_cmp] returns the result-code of a three-value comparison,
2159
+ * which is an operand representing the ordering of lhs and rhs. -1 means
2160
+ * less than, 0 means equal, 1 means greater-than.
2113
2161
*
2114
2162
* We assume that the LHS and RHS of the comparison have the same type, an
2115
- * invariant that the typechecker enforces. *)
2116
- and trans_compare_full
2117
- ~ cjmp :( cjmp :Il.jmpop )
2163
+ * invariant that the typechecker enforces.
2164
+ *)
2165
+ and trans_cmp
2118
2166
~ty_params :(ty_params :Il.cell )
2119
2167
~ty :(ty :Ast.ty )
2120
- (lhs :Il.cell )
2121
- (rhs :Il.cell )
2122
- : quad_idx list =
2168
+ (lhs :Il.operand )
2169
+ (rhs :Il.operand )
2170
+ : Il.operand =
2123
2171
let ty = strip_mutable_or_constrained_ty ty in
2124
2172
let (result:Il.cell ) = next_vreg_cell (Il. ValTy Il. Bits32 ) in
2125
- begin
2126
- match ty with
2127
- Ast. TY_obj _ ->
2128
- let lhs_binding = get_element_ptr lhs Abi. obj_field_box in
2129
- let rhs_binding = get_element_ptr rhs Abi. obj_field_box in
2130
- let lhs_box, rhs_box = deref lhs_binding, deref rhs_binding in
2131
- let lhs_obj = get_element_ptr lhs_box Abi. box_rc_field_body in
2132
- let rhs_obj = get_element_ptr rhs_box Abi. box_rc_field_body in
2133
- let tydesc = get_element_ptr lhs_obj Abi. obj_body_elt_tydesc in
2134
- let lhs_body = get_element_ptr lhs_obj Abi. obj_body_elt_fields in
2135
- let rhs_body = get_element_ptr rhs_obj Abi. obj_body_elt_fields in
2136
- trans_call_dynamic_glue
2137
- tydesc
2138
- Abi. tydesc_field_cmp_glue
2139
- (Some result)
2140
- [| alias lhs_body; alias rhs_body |]
2141
- None
2142
-
2143
- | Ast. TY_param (i , _ ) ->
2144
- trans_call_simple_dynamic_glue
2145
- i
2146
- Abi. tydesc_field_cmp_glue
2147
- ty_params
2148
- [| alias lhs; alias rhs |]
2149
- None
2173
+ begin
2174
+ match ty with
2150
2175
2151
- | _ ->
2152
- trans_call_static_glue
2153
- (code_fixup_to_ptr_operand (get_cmp_glue ty))
2154
- (Some result)
2155
- [| lhs; rhs |]
2156
- None
2157
- end ;
2158
- emit (Il. cmp (Il. Cell result) zero);
2159
- let jmp = mark() in
2160
- emit (Il. jmp cjmp Il. CodeNone );
2161
- [ jmp ]
2176
+ Ast. TY_bool
2177
+ | Ast. TY_mach _
2178
+ | Ast. TY_int
2179
+ | Ast. TY_uint
2180
+ | Ast. TY_char ->
2181
+ let cjmp =
2182
+ if type_is_unsigned_2s_complement ty
2183
+ then Il. JB
2184
+ else Il. JL
2185
+ in
2186
+ (* Start with assumption lhs < rhs *)
2187
+ mov result neg_one;
2188
+ let lhs_lt_rhs_jmps =
2189
+ trans_compare ~ty_params ~cjmp ~ty lhs rhs
2190
+ in
2191
+ (* ... disproven, so assume lhs > rhs *)
2192
+ mov result one;
2193
+ let rhs_lt_lhs_jmps =
2194
+ trans_compare ~ty_params ~cjmp ~ty rhs lhs
2195
+ in
2196
+ (* ... disproven, must be lhs == rhs *)
2197
+ mov result zero;
2198
+ List. iter patch lhs_lt_rhs_jmps;
2199
+ List. iter patch rhs_lt_lhs_jmps;
2200
+
2201
+ | Ast. TY_obj _ ->
2202
+ let lhs = need_cell lhs in
2203
+ let rhs = need_cell rhs in
2204
+ let lhs_binding = get_element_ptr lhs Abi. obj_field_box in
2205
+ let rhs_binding = get_element_ptr rhs Abi. obj_field_box in
2206
+ let lhs_box, rhs_box = deref lhs_binding, deref rhs_binding in
2207
+ let lhs_obj = get_element_ptr lhs_box Abi. box_rc_field_body in
2208
+ let rhs_obj = get_element_ptr rhs_box Abi. box_rc_field_body in
2209
+ let td = get_element_ptr lhs_obj Abi. obj_body_elt_tydesc in
2210
+ let lhs_body =
2211
+ get_element_ptr lhs_obj Abi. obj_body_elt_fields
2212
+ in
2213
+ let rhs_body =
2214
+ get_element_ptr rhs_obj Abi. obj_body_elt_fields
2215
+ in
2216
+ let ty_params_ptr = get_tydesc_params ty_params td in
2217
+ trans_call_dynamic_glue
2218
+ td Abi. tydesc_field_cmp_glue
2219
+ (Some result)
2220
+ [| ty_params_ptr; alias lhs_body; alias rhs_body |]
2221
+ None
2162
2222
2163
- (* Like [trans_compare_full], returns the address of the jump, which the
2223
+ | Ast. TY_param (i , _ ) ->
2224
+ let lhs = need_cell lhs in
2225
+ let rhs = need_cell rhs in
2226
+ let td = get_ty_param ty_params i in
2227
+ let ty_params_ptr = get_tydesc_params ty_params td in
2228
+ trans_call_dynamic_glue
2229
+ td Abi. tydesc_field_cmp_glue
2230
+ (Some result)
2231
+ [| ty_params_ptr; alias lhs; alias rhs |]
2232
+ None
2233
+
2234
+ | Ast. TY_vec _
2235
+ | Ast. TY_str ->
2236
+ (* FIXME: temporary until we get sequence-compares working. *)
2237
+ mov result zero;
2238
+
2239
+ | _ ->
2240
+ let lhs = need_cell lhs in
2241
+ let rhs = need_cell rhs in
2242
+ trans_call_static_glue
2243
+ (code_fixup_to_ptr_operand (get_cmp_glue ty))
2244
+ (Some result)
2245
+ [| alias ty_params; alias lhs; alias rhs |]
2246
+ None
2247
+ end ;
2248
+ Il. Cell result
2249
+
2250
+
2251
+ (*
2252
+ * [trans_compare_simple] returns a set of jump addresses, which the
2164
2253
* caller patches to the destination. Only use this function if you are sure
2165
2254
* that the LHS and RHS have the same type and that both will fit in a
2166
- * machine register; otherwise, use [trans_compare] instead. *)
2255
+ * machine register; otherwise, use [trans_compare] instead.
2256
+ *)
2167
2257
and trans_compare_simple
2168
2258
(cjmp :Il.jmpop )
2169
2259
(lhs :Il.operand )
@@ -2174,20 +2264,34 @@ let trans_visitor
2174
2264
emit (Il. jmp cjmp Il. CodeNone );
2175
2265
[ jmp ]
2176
2266
2267
+ (*
2268
+ * [trans_compare] returns a set of jump addresses, which the
2269
+ * caller patches to the destination.
2270
+ *)
2177
2271
and trans_compare
2178
2272
?ty_params :(ty_params = get_ty_params_of_current_frame() )
2179
2273
~cjmp: (cjmp:Il.jmpop )
2180
2274
~ty: (ty:Ast.ty )
2181
2275
(lhs:Il.operand )
2182
2276
(rhs:Il.operand )
2183
2277
: quad_idx list =
2184
- ignore (trans_compare ~cjmp ~ty lhs rhs);
2185
- (* TODO *)
2186
- match lhs, rhs with
2187
- Il. Cell lhs , Il. Cell rhs ->
2188
- trans_compare_full
2189
- ~cjmp ~ty_params ~ty lhs rhs
2190
- | _ -> trans_compare_simple cjmp lhs rhs
2278
+ match ty with
2279
+ Ast. TY_bool
2280
+ | Ast. TY_mach _
2281
+ | Ast. TY_int
2282
+ | Ast. TY_uint
2283
+ | Ast. TY_char ->
2284
+ trans_compare_simple cjmp lhs rhs
2285
+
2286
+ | _ ->
2287
+ let result =
2288
+ trans_cmp ~ty_params ~ty lhs rhs
2289
+ in
2290
+ emit (Il. cmp result zero);
2291
+ let jmp = mark() in
2292
+ emit (Il. jmp cjmp Il. CodeNone );
2293
+ [ jmp ]
2294
+
2191
2295
2192
2296
and trans_cond (invert :bool ) (expr :Ast.expr ) : quad_idx list =
2193
2297
let anno _ =
@@ -2198,27 +2302,27 @@ let trans_visitor
2198
2302
" : cond, finale" )
2199
2303
end
2200
2304
in
2201
-
2202
- match expr with
2203
- Ast. EXPR_binary ( binop , a , b ) ->
2204
- let lhs = trans_atom a in
2205
- let rhs = trans_atom b in
2206
- let cjmp = binop_to_jmpop binop in
2207
- let cjmp' =
2208
- if invert then
2209
- match cjmp with
2210
- Il. JE -> Il. JNE
2211
- | Il. JNE -> Il. JE
2212
- | Il. JL -> Il. JGE
2213
- | Il. JLE -> Il. JG
2214
- | Il. JGE -> Il. JL
2215
- | Il. JG -> Il. JLE
2216
- | _ -> bug () " Unhandled inverse binop in trans_cond "
2217
- else
2218
- cjmp
2219
- in
2220
- anno () ;
2221
- trans_compare_simple cjmp' lhs rhs
2305
+ match expr with
2306
+ Ast. EXPR_binary ( binop , a , b ) ->
2307
+ let lhs = trans_atom a in
2308
+ let rhs = trans_atom b in
2309
+ let cjmp = binop_to_jmpop binop in
2310
+ let cjmp =
2311
+ if invert then
2312
+ match cjmp with
2313
+ Il. JE -> Il. JNE
2314
+ | Il. JNE -> Il. JE
2315
+ | Il. JL -> Il. JGE
2316
+ | Il. JLE -> Il. JG
2317
+ | Il. JGE -> Il. JL
2318
+ | Il. JG -> Il. JLE
2319
+ | _ -> bug () " Unhandled inverse binop in trans_cond "
2320
+ else
2321
+ cjmp
2322
+ in
2323
+ anno () ;
2324
+ let ty = atom_type cx a in
2325
+ trans_compare ~ cjmp ~ty lhs rhs
2222
2326
2223
2327
| _ ->
2224
2328
let bool_operand = trans_expr expr in
0 commit comments