finding GHC assembly for a function - haskell

I'd like to identify what assembly GHC produces for a given function.
Here, for example, is some code which (should) rotate bits around in a word - it moves bit 0 to bit 12, bit 12 to 14, bit 14 back to 0 and similarly for the positions 1, 18, 13 and 6.
What's the best way to go about finding the assembly generated for rot0cw in the .S file produced by ghc -O2 -S ...?
I've read this answer, but I don't see any ..._rot0cw_closure in the assembly output.
import Data.Bits
import Data.Int (Int64)
import Text.Printf
import System.Environment
{-# INLINE maskbits #-}
-- set in word v the bits of b corresponding to the mask m
-- assume a bit in b is zero if not in the mask
maskbits v m b = (v .&. (complement m) .|. b)
{-# INLINE tb #-}
-- transfer bit i of word v to bit j of word m; assume bit j of m is 0
tb v i j m = m .|. (rotate (v .&. (bit i)) (j-i))
rot0cw :: Int64 -> Int64
rot0cw v = maskbits (maskbits v m1 b1) m2 b2
where
m1 = 0x0000005005
b1 = tb v 0 2 . tb v 2 14 . tb v 14 12 . tb v 12 0 $ 0
m2 = 0x0000002142
b2 = tb v 1 8 . tb v 8 13 . tb v 13 6 . tb v 6 1 $ 0
showBits v =
let set = [ i | i <- [0..35], testBit v i ]
in "bits set: " ++ (unwords $ map show set)
main = do
(arg0:_) <- getArgs
let v = read arg0
-- let v = 0x0000000005
let v' = rot0cw v
putStrLn $ printf "v = 0x%010x = %12d %s" v v (showBits v)
putStrLn $ printf "v' = 0x%010x = %12d %s" v' v' (showBits v')

I've read this answer, but I don't see any ..._rot0cw_closure in the assembly output.
You need to name your module. e.g. add module Main where at the beginning* to get Main_rot0cw_closure in the generated assembly.
* Strictly speaking, your module needs to export the function.

You will need to export the function rot0cw from your module, otherwise it's effectively dead code. So add something like this to the top of your module:
module Asm(rot0cw) where
The assembly it generates is rather large, if you dump the Cmm -ddump-cmm you can look at each of the proc blocks labeled with the name of the function you're interested in. The basic blocks GHC generates here roughly corresponds to a label in the resulting assembly. So for instance the entry code for rot0cw_closure maps to the following:
cB2:
if (Sp - 32 < SpLim) goto cB4;
Hp = Hp + 16;
if (Hp > HpLim) goto cB6;
I64[Sp - 16] = stg_upd_frame_info;
I64[Sp - 8] = R1;
I64[Hp - 8] = S#_con_info;
I64[Hp + 0] = 0;
I64[Sp - 24] = Hp - 7;
I64[Sp - 32] = stg_ap_p_info;
R2 = $fNumInt64_closure;
Sp = Sp - 32;
jump fromInteger_info; // [R2]
cB4: jump stg_gc_enter_1; // [R1]
cB6:
HpAlloc = 16;
goto cB4;
Which generates out to:
_cB2:
leaq -32(%rbp),%rax
cmpq %r15,%rax
jb _cB4
addq $16,%r12
cmpq 144(%r13),%r12
ja _cB6
movq $stg_upd_frame_info,-16(%rbp)
movq %rbx,-8(%rbp)
movq $S#_con_info,-8(%r12)
movq $0,0(%r12)
leaq -7(%r12),%rax
movq %rax,-24(%rbp)
movq $stg_ap_p_info,-32(%rbp)
movl $$fNumInt64_closure,%r14d
addq $-32,%rbp
jmp fromInteger_info
_cB6:
movq $16,192(%r13)
_cB4:
jmp *-16(%r13)
.size sat_info, .-sat_info
Invariably you'll get a lot of "noise" from all the the GC functions and various runtime calls, and opaque predefined closure objects. But if you really want to dig into the generated looking at the Cmm first is the way to go.

Related

RPGLE code to RPG - Count number of Digits

I am having an issue with coding this, I need some similar code with this but written in RPG to count the digits in a number.
NumField (15, 0) packed decimal
EVAL numDig = %len(%trim(%char(NumField)))
the %editc built in function dates back to the begin of time. So does %len, %trim and varying fields.
** ---------------------- test0003r ---------------------------
dtest0003r pi
d errmsg s 256a
d packNum s 15p 0
d lx s 10i 0
d v20 s 20a varying
d ch50 s 50a
/free
packNum = 32553;
v20 = %trim(%editc(packNum:'Z')) ;
lx = %len(v20) ;
ch50 = %trim(%editc(lx:'Z')) + ' ' + v20 ;
dsply ch50 ;
*inlr = '1' ;
return ;
/end-free
A fun challenge.
#zen, I agree with others. I would not try to code this in RPG III. I would either convert the RPG III program to RPG IV, or I would call an RPG IV program to do this calculation.
But here is some RPG III code that gets the number of digits. It is horrible code, and almost completely untested. I would never use this code or recommend that anyone else use this code.
C Z-ADD1.2 NUM 52
C EXSR SUB1
C Z-ADD-123.45 NUM 52
C EXSR SUB1
C Z-ADD0 NUM 52
C EXSR SUB1
C RETRN
C SUB1 BEGSR
C MOVELNUM STR 30 P
C '0':' ' XLATESTR STR2 30 P
C ' ' CHECKSTR2 P 50
C P IFGT 0
C SUBSTSTR2:P STR3 30 P
C ' ' CHEKRSTR3 P 50
C ENDIF
C P DSPLY
C ENDSR
It displays 2, 5, 0.

Problem with GCC compiler

I am using Arch Linux and when I am compiling and running the following C code,
#include <stdio.h>
#include<string.h>
int main(void) {
char s1[]="Hello";
char s2[]="World";
strcat(s1,s2);
int s2_len=strlen(s2);
printf("s1 = %s, s2 = %s and length of s2 = %d.\n", s1, s2, s2_len);
return 0;
}
I am getting the output:
s1 = HelloWorld, s2 = orld and length of s2 = 4.
Although the output shoud be s1 = HelloWorld, s2 = World and length of s2 = 5. and it is the output when I am using some online IDE.
Can somebody explain me why is this happening?
char s1[]="Hello";
char s2[]="World";
strcat(s1,s2);
The variable declarations allocate memory for 5 characters each, plus the terminating NUL byte. Your strcat call writes past that space, which produces undefined results.
In this case, the memory layout is probably something like this
0 1 2 3 4 5 6 7 8 9 10 11
H e l l o \0 W o r l d \0
^ ^
s1 s2
After the strcat, the result is:
0 1 2 3 4 5 6 7 8 9 10 11
H e l l o W o r l d \0 \0
^ ^
s1 s2
Which gives the result you see. Note that there could be other possible results, the program could e.g. crash at the strcat call.

Load image from file in Ocaml Graphics

I'm reading the documentation for the Graphics module, and there isn't any information on loading images from a file, only from a colour array. How would I go about doing this? For example, suppose I have file.png, and I want to draw it at co-ordinates (x, y) with z degrees rotation.
The camlimages library can load png files (if they are not represented in RGBA or CMYK format). A simple example:
open Images
let () = Graphics.open_graph "";;
let img = Png.load "png.png" [];;
let g = Graphic_image.of_image img;;
Graphics.draw_image g 0 0;;
Unix.sleep 10;;
To run:
opam install graphics camlimages
ocamlfind ocamlc -o test -package graphics -package unix \
-package camlimages.png -package camlimages.graphics \
-linkpkg test.ml
wget https://bytebucket.org/camlspotter/camlimages/raw/1611545463f493462aeafab65839c1112162559a/test/images/png.png
./test
(Based on the example in the library source code.)
But, I don't think camlimages can rotate pngs. You could roll your own rotate function (adapted from Mortimer's code on Dr. Dobb's):
let rotate src dst angle =
let sh, sw = Array.(float (length src), float (length src.(0))) in
let dh, dw = Array.(length dst, length dst.(0)) in
let dx, dy = float dw /. 2., float dh /. 2. in
let scale = min (float dh /. sh) (float dw /. sw) in
let duCol = sin(-.angle) *. (1. /. scale) in
let dvCol = cos(-.angle) *. (1. /. scale) in
let rec col dst x u v =
if x < dw then (
dst.(x) <- if (0. <= u && u < sw) && (0. <= v && v < sh)
then src.(truncate v).(truncate u)
else Graphics.white;
col dst (x + 1) (u +. dvCol) (v -. duCol))
in
let rec row y rowu rowv =
if y < dh then (col dst.(y) 0 rowu rowv;
row (y + 1) (rowu +. duCol) (rowv +. dvCol))
in
row 0 ((sw /. 2.) -. (dx *. dvCol +. dy *. duCol))
((sh /. 2.) -. (dx *. (-.duCol) +. dy *. dvCol))
And call it from the example code above with
let dg = Graphics.dump_image g
let dgr =Array.(make_matrix (length dg) (length dg.(0)) Graphics.white);;
rotate dg dgr (4. *. atan 1. /. 2);;
let g = Graphics.make_image dgr;;
Or, you could use something like the Sdlgfx.rotozoomSurface function of OCamlSDL.
A simple example:
let png = Sdlloader.load_image "png.png"
let png_rot = Sdlgfx.rotozoomSurface png 45.0 1.0 true;;
Sdl.init [`VIDEO];;
let screen = Sdlvideo.set_video_mode ~w:250 ~h:166 [];;
Sdlvideo.(blit_surface ~dst_rect:{ r_x = 0; r_y = 0; r_w = 250; r_h = 166}
~src:png_rot ~dst:screen ());;
Sdlvideo.flip screen;
Sdltimer.delay 10000;
Sdl.quit ();;
After installing the appropriate SDL packages on your system (not always easy...), to run:
opam install ocamlsdl
ocamlfind ocamlc -o test -package sdl -package sdl.sdlimage \
-package sdl.sdlgfx -linkpkg test.ml
./test

ARM Assembly accepting '-'

So my code currently converts a string into a integer. My code is currently working and functional however, i need it to accept an "-" at the beginning of the input to judge if it is a negative or not. I have no idea how to do this and i can not find any sources. I am currently passing in (test3: .asciz "-48") into register r0. and when i run in the debugger i am receiving 45. here is my code for reference.
.global stoi
.text
stoi:
push {r4,r5,r6,r8,r9,lr}
#r0 = buffer
mov r1,#0 #r1 = n = 0
mov r9,#0 #buffer counter
mov r4,#48 #0 checker
mov r5,#57 #9 checker
b 5f
5:
ldrb r3,[r0,r9] #r3 = c
b 1f
1:
cmp r3,r4 #cmp c to 0(48 in ASCII)
bge 2f
b 4f
2:
cmp r3,r5 #cmp c to 9(57 in ASCII)
ble 3f
b 4f
3:
sub r6,r3,#'0' #r6 = (c - '0')
#strb r6,[r0,r9]
add r1,r1,r1,lsl#2 #r1 = n * 10
add r1,r1,r1,lsl#0
add r1,r1,r6 #n = n * 10 + (c - '0')
add r9,r9,#1 #add to buffer
b 5b
4:
mov r0,r1
pop {r4,r5,r6,r8,r9,pc}
use the same code you're using now, and add these changes:
1) skip the '-' if it's the first char.
Right now you're stopping if a non-digit char is read, you receive 45 (in R3), it is the ascii of '-'. Afais R1 should still be 0 tho
2) At the end, add a check if the first char is a '-', and if it is, subtract r1 from 0 (since 0 - x is -x)
( 3) remove the b 1f, it's not needed ;) )

reading integers from a string

I want to read a line from a file, initialize an array from that line and then display the integers.
Why is is not reading the five integers in the line? I want to get output 1 2 3 4 5, i have 1 1 1 1 1
open Array;;
open Scanf;;
let print_ints file_name =
let file = open_in file_name in
let s = input_line(file) in
let n = ref 5 in
let arr = Array.init !n (fun i -> if i < !n then sscanf s "%d" (fun a -> a) else 0) in
let i = ref 0 in
while !i < !n do
print_int (Array.get arr !i);
print_string " ";
i := !i + 1;
done;;
print_ints "string_ints.txt";;
My file is just: 1 2 3 4 5
You might want to try the following approach. Split your string into a list of substrings representing numbers. This answer describes one way of doing so. Then use the resulting function in your print_ints function.
let ints_of_string s =
List.map int_of_string (Str.split (Str.regexp " +") s)
let print_ints file_name =
let file = open_in file_name in
let s = input_line file in
let ints = ints_of_string s in
List.iter (fun i -> print_int i; print_char ' ') ints;
close_in file
let _ = print_ints "string_ints.txt"
When compiling, pass str.cma or str.cmxa as an argument (see this answer for details on compilation):
$ ocamlc str.cma print_ints.ml
Another alternative would be using the Scanf.bscanf function -- this question, contains an example (use with caution).
The Scanf.sscanf function may not be particularly suitable for this task.
An excerpt from the OCaml manual:
the scanf facility is not intended for heavy duty lexical analysis and parsing. If it appears not expressive enough for your needs, several alternative exists: regular expressions (module Str), stream parsers, ocamllex-generated lexers, ocamlyacc-generated parsers
There is though a way to parse a string of ints using Scanf.sscanf (which I wouldn't recommend):
let rec int_list_of_string s =
try
Scanf.sscanf s
"%d %[0-9-+ ]"
(fun n rest_str -> n :: int_list_of_string rest_str)
with
| End_of_file | Scanf.Scan_failure _ -> []
The trick here is to represent the input string s as a part which is going to be parsed into a an integer (%d) and the rest of the string using the range format: %[0-9-+ ]", which will match the rest of the string, containing only decimal digits 0-9, the - and + signs, and whitespace .

Resources