Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] View of /branches/vis15/src/compiler/cxx-util/gen-outputs-util.sml
ViewVC logotype

View of /branches/vis15/src/compiler/cxx-util/gen-outputs-util.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4317 - (download) (annotate)
Sat Jul 30 14:12:14 2016 UTC (3 years, 5 months ago) by jhr
File size: 9755 byte(s)
working on merge: expand tabs to eight spaces
(* gen-outputs-util.sml
 *
 * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu)
 *
 * COPYRIGHT (c) 2015 The University of Chicago
 * All rights reserved.
 *
 * Target-independent code for generating the output code.
 *)

structure GenOutputsUtil : sig

    type output_info = OutputUtil.output_info

  (* code fragment to allocate nrrd data and check for errors *)
    val maybeAlloc : CodeGenEnv.t * CLang.exp * CLang.var * int -> CLang.stm

  (* generate code to register command-line options for redirecting the output in standalone
   * executables.  This function returns a list consisting of the global C variables that hold
   * the option values and the registration function.
   *)
    val genRegisterOutputOpts : CodeGenEnv.t * output_info list -> CLang.decl list

  (* generate the nrrd-file output and print functions used by standalone executables *)
    val genOutput : CodeGenEnv.t * output_info list -> CLang.decl list

  end = struct

    structure Ty = APITypes
    structure CL = CLang
    structure Env = CodeGenEnv
    structure RN = CxxNames

    type output_info = OutputUtil.output_info

    val nrrdPtrTy = CL.T_Ptr(CL.T_Named "Nrrd")
    val filePtrTy = CL.T_Ptr(CL.T_Named "FILE")

    val outputGet = GenLibraryInterface.outputGet

  (* variables in the generated code *)
    val wrldV = CL.mkVar "wrld"
    val sizesV = CL.mkVar "sizes"
    val nDataV = CL.mkVar "nData"
    val nLengthsV = CL.mkVar "nLengths"
    val NRRD = CL.mkVar "NRRD"
    val msgV = CL.mkVar "msg"

  (* code fragment to allocate nrrd data and check for errors
        if (nrrdMaybeAlloc_nva(<nrrdVar>, <nrrdType>, <nDims>, sizes) != 0) {
            char *msg = biffGetDone(NRRD);
            biffMsgAdd (wrld->_errors, msg);
            std::free (msg);
            return true;
        }
   *)
    fun maybeAlloc (env, nrrdVar, nrrdType, nDims) =
          CL.mkIfThen(
            CL.mkBinOp(
              CL.mkApply("nrrdMaybeAlloc_nva", [
                  nrrdVar, CL.mkVar nrrdType, CL.mkInt(IntInf.fromInt nDims), sizesV
                ]),
              CL.#!=,
              CL.mkInt 0),
          (* then *)
            CL.mkBlock[
                CL.mkDeclInit(CL.charPtr, "msg", CL.mkApply("biffGetDone", [NRRD])),
                TreeToCxx.errorMsgAdd (env, msgV),
                CL.mkCall("std::free", [msgV]),
                CL.mkReturn(SOME(CL.mkVar "true"))
              ]
          (* endif*))

  (* global variable names for output file/stems *)
    val outfile = "Outfile"
    fun outstem name = "OutStem_" ^ name

  (* generate code to register command-line options for redirecting the output in standalone
   * executables.
   *)
    fun genRegisterOutputOpts (env, outputs : output_info list) = let
        (* some common variables *)
          val optsV = CL.mkVar "opts"
        (* make a global variable declaration *)
          fun mkDecl (name, value) =
                CL.D_Var(["static"], CL.T_Named "std::string", [], name,
                  SOME(CL.I_Exp(CL.mkStr value)))
        (* register a flag for a given output *)
          fun registerOutput {name, ty, isGlobal} = let
                val optName = "redirect-" ^ name
                in
                  CL.mkExpStm(CL.mkIndirectDispatch(optsV, "add", [
                      CL.mkStr(concat["o-", name, ",", "output-", name]),
                      CL.mkStr("specify output-file stem for " ^ name),
                      CL.mkUnOp(CL.%&, CL.mkVar(outstem name)),
                      CL.mkBool true
                    ]))
                end
          fun multi () = let
                val stms = List.map registerOutput outputs
                val dcls = List.map (fn {name, ...} => mkDecl (outstem name, name)) outputs
                in
                  (stms, dcls)
                end
          val (stms, dcls) = (case outputs
                 of [{ty = Ty.SeqTy(_, NONE), ...}] => multi () (* two ouput files *)
                  | [{name, ...}] => let (* one output file, so use "-o" redirect option *)
                      val stm = CL.mkExpStm(CL.mkIndirectDispatch(optsV, "add", [
                          CL.mkStr "o,output", CL.mkStr("specify output-file file"),
                          CL.mkUnOp(CL.%&, CL.mkVar outfile),
                          CL.mkBool true
                        ]))
                      val dcl = mkDecl (outfile, name ^ ".nrrd")
                      in
                        ([stm], [dcl])
                      end
                  | _ => multi ()
                (* end case *))
          val registerFn = CL.D_Func(
                ["static"], CL.voidTy, [], "register_outputs",
                [CL.PARAM([], RN.optionsPtrTy env, "opts")],
                CL.mkBlock stms)
          in
            dcls @ [registerFn]
          end

  (* generate the nrrd-file output and print functions used by standalone executables *)
    fun genOutput (env, outputs : output_info list) = let
          val spec = Env.target env
          fun isDyn ty = (case ty of Ty.SeqTy(_, NONE) => true | _ => false)
(* FIXME: use biffMsgAddF and return error status *)
          fun error msg = CL.mkBlock[
                  CL.mkExpStm(List.foldl
                    (fn (e, lhs) => CL.mkBinOp(lhs, CL.#<<, e))
                      (CL.mkVar "std::cerr")
                        (msg @ [CL.mkVar "std::endl"])),
                  CL.mkCall("exit", [CL.mkInt 1])
                ]
          val outDecls = if List.exists (isDyn o #ty) outputs
                then [CL.mkDecl(nrrdPtrTy, "nLengths", NONE), CL.mkDecl(nrrdPtrTy, "nData", NONE)]
                else [CL.mkDecl(nrrdPtrTy, "nData", NONE)]
          val prDecls = outDecls @ [CL.mkDecl(filePtrTy, "outS", NONE)]
          fun nrrdNew v = CL.mkAssign(v, CL.mkApply("nrrdNew", []))
          fun nrrdNuke v = CL.mkCall("nrrdNuke", [v])
          val isMultiOutput = (case outputs
                 of [{ty, ...}] => isDyn ty
                  | _ => true
                (* end case *))
          fun writeNrrd {name, ty, isGlobal} = if isDyn ty
                then [
                    nrrdNew (nLengthsV),
                    nrrdNew (nDataV),
                    CL.mkIfThenElse(
                      CL.mkApply(outputGet(spec, name), [wrldV, nLengthsV, nDataV]),
                    (* then *)
                        error [
                            CL.mkStr "Error getting nrrd data:\n",
                            CL.mkApply("biffMsgStrGet", [CL.mkIndirect(wrldV, "_errors")])
                          ],
                    (* else *)
                      CL.mkIfThen(
                        CL.mkBinOp(
                          CL.mkApply("NrrdSaveHelper", [
                              CL.mkVar(outstem name), CL.mkStr "-len", CL.mkStr "nrrd", nLengthsV
                            ]),
                          CL.#||,
                          CL.mkApply("NrrdSaveHelper", [
                              CL.mkVar(outstem name), CL.mkStr "-data", CL.mkStr "nrrd", nDataV
                            ])),
                      (* then *)
                        error [
                            CL.mkStr "Error saving nrrd:\n",
                            CL.mkApply("biffGetDone", [NRRD])
                          ]
                      (* endif *))
                    (* endif *)),
                    nrrdNuke nLengthsV,
                    nrrdNuke nDataV
                  ]
              else if isMultiOutput
                then [
                    nrrdNew (nDataV),
                    CL.mkIfThenElse(
                      CL.mkApply(outputGet(spec, name), [wrldV, nDataV]),
                    (* then *)
                        error [
                            CL.mkStr "Error getting nrrd data:\n",
                            CL.mkApply("biffMsgStrGet", [CL.mkIndirect(wrldV, "_errors")])
                          ],
                    (* else *)
                      CL.mkIfThen(
                        CL.mkApply("NrrdSaveHelper", [
                            CL.mkVar(outstem name), CL.mkStr "", CL.mkStr "nrrd", nDataV
                          ]),
                      (* then *)
                        error [
                            CL.mkStr "Error saving nrrd:\n",
                            CL.mkApply("biffGetDone", [NRRD])
                          ]
                      (* endif *))
                    (* endif *)),
                    nrrdNuke nDataV
                  ]
                else [
                    nrrdNew (nDataV),
                    CL.mkIfThenElse(
                      CL.mkApply(outputGet(spec, name), [wrldV, nDataV]),
                    (* then *)
                        error [
                            CL.mkStr "Error getting nrrd data:\n",
                            CL.mkApply("biffMsgStrGet", [CL.mkIndirect(wrldV, "_errors")])
                          ],
                    (* else *)
                      CL.mkIfThen(
                        CL.mkApply("nrrdSave", [
                            CL.mkDispatch(CL.mkVar outfile, "c_str", []), nDataV, CL.mkVar "NULL"
                          ]),
                      (* then *)
                        error [
                            CL.mkStr "Error saving nrrd:\n",
                            CL.mkApply("biffGetDone", [NRRD])
                          ]
                      (* endif *))
                    (* endif *)),
                    nrrdNuke nDataV
                  ]
          in [
            CL.D_Func(
              ["static"], CL.voidTy, [], "write_output",
              [CL.PARAM([], RN.worldPtrTy, "wrld")],
              CL.mkBlock(outDecls @ List.foldr (fn (output, l) => writeNrrd output @ l) [] outputs))
          ] end

  end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0