Task

Create and display the sequence of binary digits for a given   non-negative integer.

   The decimal value      5   should produce an output of               101
   The decimal value     50   should produce an output of            110010
   The decimal value   9000   should produce an output of    10001100101000

The results can be achieved using built-in radix functions within the language   (if these are available),   or alternatively a user defined function can be used.

The output produced should consist just of the binary digits of each number followed by a   newline.

There should be no other whitespace, radix or sign markers in the produced output, and leading zeros should not appear in the results.




; ModuleID = 'binary.c'
; source_filename = "binary.c"
; target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
; target triple = "x86_64-pc-windows-msvc19.21.27702"
 
; This is not strictly LLVM, as it uses the C library function "printf".
; LLVM does not provide a way to print values, so the alternative would be
; to just load the string into memory, and that would be boring.
 
; Additional comments have been inserted, as well as changes made from the output produced by clang such as putting more meaningful labels for the jumps
 
$"\01??_C@_03OFAPEBGM@?$CFs?6?$AA@" = comdat any
 
;--- String constant defintions
@"\01??_C@_03OFAPEBGM@?$CFs?6?$AA@" = linkonce_odr unnamed_addr constant [4 x i8] c"%s\0A\00", comdat, align 1
 
;--- The declaration for the external C printf function.
declare i32 @printf(i8*, ...)
 
;--- The declaration for the external C log10 function.
declare double @log10(double) #1
 
;--- The declaration for the external C malloc function.
declare noalias i8* @malloc(i64) #2
 
;--- The declaration for the external C free function.
declare void @free(i8*) #2
 
;----------------------------------------------------------
;-- Function that allocates a string with a binary representation of a number
define i8* @bin(i32) #0 {
;-- uint32_t x (local copy)
  %2 = alloca i32, align 4
;-- size_t bits
  %3 = alloca i64, align 8
;-- intermediate value
  %4 = alloca i8*, align 8
;-- size_t i
  %5 = alloca i64, align 8
  store i32 %0, i32* %2, align 4
;-- x == 0, start determinig what value to initially store in bits
  %6 = load i32, i32* %2, align 4
  %7 = icmp eq i32 %6, 0
  br i1 %7, label %just_one, label %calculate_logs
 
just_one:
  br label %assign_bits
 
calculate_logs:
;-- log10((double) x)/log10(2) + 1
  %8 = load i32, i32* %2, align 4
  %9 = uitofp i32 %8 to double
;-- log10((double) x)
  %10 = call double @log10(double %9) #3
;-- log10(2)
  %11 = call double @log10(double 2.000000e+00) #3
;-- remainder of calculation
  %12 = fdiv double %10, %11
  %13 = fadd double %12, 1.000000e+00
  br label %assign_bits
 
assign_bits:
;-- bits = (x == 0) ? 1 : log10((double) x)/log10(2) + 1;
;-- phi basically selects what the value to assign should be based on which basic block came before
  %14 = phi double [ 1.000000e+00, %just_one ], [ %13, %calculate_logs ]
  %15 = fptoui double %14 to i64
  store i64 %15, i64* %3, align 8
;-- char *ret = malloc((bits + 1) * sizeof (char));
  %16 = load i64, i64* %3, align 8
  %17 = add i64 %16, 1
  %18 = mul i64 %17, 1
  %19 = call noalias i8* @malloc(i64 %18)
  store i8* %19, i8** %4, align 8
  store i64 0, i64* %5, align 8
  br label %loop
 
loop:
;-- i < bits;
  %20 = load i64, i64* %5, align 8
  %21 = load i64, i64* %3, align 8
  %22 = icmp ult i64 %20, %21
  br i1 %22, label %loop_body, label %exit
 
loop_body:
;-- ret[bits - i - 1] = (x & 1) ? '1' : '0';
  %23 = load i32, i32* %2, align 4
  %24 = and i32 %23, 1
  %25 = icmp ne i32 %24, 0
  %26 = zext i1 %25 to i64
  %27 = select i1 %25, i32 49, i32 48
  %28 = trunc i32 %27 to i8
  %29 = load i8*, i8** %4, align 8
  %30 = load i64, i64* %3, align 8
  %31 = load i64, i64* %5, align 8
  %32 = sub i64 %30, %31
  %33 = sub i64 %32, 1
  %34 = getelementptr inbounds i8, i8* %29, i64 %33
  store i8 %28, i8* %34, align 1
;-- x >>= 1;
  %35 = load i32, i32* %2, align 4
  %36 = lshr i32 %35, 1
  store i32 %36, i32* %2, align 4
  br label %loop_increment
 
loop_increment:
;-- i++;
  %37 = load i64, i64* %5, align 8
  %38 = add i64 %37, 1
  store i64 %38, i64* %5, align 8
  br label %loop
 
exit:
;-- ret[bits] = '\0';
  %39 = load i8*, i8** %4, align 8
  %40 = load i64, i64* %3, align 8
  %41 = getelementptr inbounds i8, i8* %39, i64 %40
  store i8 0, i8* %41, align 1
;-- return ret;
  %42 = load i8*, i8** %4, align 8
  ret i8* %42
}
 
;----------------------------------------------------------
;-- Entry point into the program
define i32 @main() #0 {
;-- 32-bit zero for the return
  %1 = alloca i32, align 4
;-- size_t i, for tracking the loop index
  %2 = alloca i64, align 8
;-- char* for the result of the bin call
  %3 = alloca i8*, align 8
;-- initialize
  store i32 0, i32* %1, align 4
  store i64 0, i64* %2, align 8
  br label %loop
 
loop:
;-- while (i < 20)
  %4 = load i64, i64* %2, align 8
  %5 = icmp ult i64 %4, 20
  br i1 %5, label %loop_body, label %exit
 
loop_body:
;-- char *binstr = bin(i);
  %6 = load i64, i64* %2, align 8
  %7 = trunc i64 %6 to i32
  %8 = call i8* @bin(i32 %7)
  store i8* %8, i8** %3, align 8
;-- printf("%s\n", binstr);
  %9 = load i8*, i8** %3, align 8
  %10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01??_C@_03OFAPEBGM@?$CFs?6?$AA@", i32 0, i32 0), i8* %9)
;-- free(binstr);
  %11 = load i8*, i8** %3, align 8
  call void @free(i8* %11)
  br label %loop_increment
 
loop_increment:
;-- i++
  %12 = load i64, i64* %2, align 8
  %13 = add i64 %12, 1
  store i64 %13, i64* %2, align 8
  br label %loop
 
exit:
;-- return 0 (implicit)
  %14 = load i32, i32* %1, align 4
  ret i32 %14
}
 
attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #3 = { nounwind }
 
!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}
 
!0 = !{i32 1, !"wchar_size", i32 2}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{!"clang version 6.0.1 (tags/RELEASE_601/final)"}