let generate_code source_fname procs =
  let ret = ref (
    "\t.file\t\"" ^ source_fname ^ "\"\n" ^
    "\t.section\t.rodata\n.WI:\n\t.string\t\"%d\\n\"\n" ^
    "\t.text\n"
  )
  in
  let code_of_proc p =
    
    (** @return the code for an eventual unspill and the register's name. *)

    let code_of_var v =
      match v.var_def.vd_value with
        | Some(Integer i) -> """$" ^ (string_of_int i)
        | _ ->
            (
              match v.var_reg with
                | Some 0 -> """%eax"
                | Some 1 -> """%ebx"
                | Some 2 -> """%ecx"
                | Some 3 -> """%edx"
                | Some 4 -> """%eax" (* TODO: !!!!! *)
                | Some n -> """%reg" ^ (string_of_int n)
                    (* TODO *)
                | None -> """%fuck"
            )
    in
    let code_of_instr = function
      | Addi(v1, v2, v3) ->
          let i1, r1 = code_of_var v1 in
          let i2, r2 = code_of_var v2 in
          let i3, r3 = code_of_var v3 in
            "\taddl\t" ^ r3 ^ ", " ^ r2 ^ "\n" ^
            "\tmovl\t" ^ r2 ^ ", " ^ r1 ^ "\n"
      | Movi(v1, v2) ->
          let i1, r1 = code_of_var v1 in
          let i2, r2 = code_of_var v2 in
            "\tmovl\t" ^ r2 ^ ", " ^ r1 ^ "\n"
      | ExtCall(n, l) ->
          (
            match n with
              | "writeInt" ->
                  let i1, r1 = code_of_var (List.hd l) in
                    "\tmov\t" ^ r1 ^ ", 4(%esp)\n" ^ "\tmovl\t$.WI, (%esp)\n" ^ "\tcall\tprintf\n"
              | _ -> "\tcall " ^ n ^ "\n" (* TODO *)
          )
      | Nop -> "\tnop\n"
    in
      ret := !ret ^
      ".globl " ^ p.proc_name ^ "\n" ^
      "\t.type\t" ^ p.proc_name ^ ", @function\n" ^ p.proc_name ^ ":\n" ^
      "\tpushl\t%ebp\n" ^ "\tmovl\t%esp, %ebp\n";
      ret := !ret ^ (* TODO: allocation on the stack *)
      "\tsubl\t$24, %esp\n";
      ret := !ret ^ List.fold_left (fun s i -> s ^ code_of_instr i) "" p.proc_value.bb_block ^
      "\tmov\t$0, %eax\n" ^ (* TODO: not eveywhere? *)
      "\tleave\n\tret\n" (* TODO: what's that exactly? leave everywhere? *)
  in
    List.iter (fun p -> code_of_proc p) procs; !ret ^ "\t.size\tmain, .-main\n" ^ "\t.section\t.note.GNU-stack,\"\",@progbits\n" ^ "\t.ident\t\"Bifton 0.1.0\"\n"