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

SCM Repository

[diderot] View of /branches/vis15/src/compiler/target-cpu/gen-inputs.sml
ViewVC logotype

View of /branches/vis15/src/compiler/target-cpu/gen-inputs.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3910 - (download) (annotate)
Tue May 24 21:55:24 2016 UTC (3 years, 1 month ago) by jhr
File size: 13957 byte(s)
working on merge
(* gen-inputs.sml
 *
 * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu)
 *
 * COPYRIGHT (c) 2016 The University of Chicago
 * All rights reserved.
 *
 * Generate code to handle input variables for the C target.
 *)

structure GenInputs : sig

  (* input variable descriptor: type, name, description, and default *)
    type input_desc = GenInputsUtil.input_desc

  (*** Support for standalone executables ***)

  (* generate the input initialization structure that we use to initialize input
   * globals from command-line arguments in stand-alone executables.
   *)
    val genInputsStruct : CodeGenEnv.t * input_desc list -> CLang.decl list

  (* generate the functions that handle inputs for standalone executables.  These are:
   *    InitDefaults    -- called to initialize the default input values
   *    RegisterInputs  -- called to register the command-line options for the input globals
   *    InitInputs      -- called to initialize the input globals from the values specified
   *                       on the command line.
   *)
    val genExecInputFuns : CodeGenEnv.t * input_desc list -> CLang.decl list

  (*** Support for libraries ***)

  (* generate the typedef for the defined-input flag struct. *)
    val genDefinedInpStruct : CodeGenEnv.t * input_desc list -> CLang.decl list

  (* generated the functions to initialize inputs for the library API.  This function also
   * generates the function to initialize the defined input flags struct.
   *)
    val genInputFuns : CodeGenEnv.t * input_desc list -> CLang.decl list

  end = struct

    structure IR = TreeIR
    structure Ty = TreeIR.Ty
    structure GVar = TreeGlobalVar
    structure CL = CLang
    structure RN = CxxNames
    structure ToC = TreeToCxx
    structure TrTy = CTyTranslate
    structure U = GenInputsUtil
    structure Env = CodeGenEnv

    type input_desc = U.input_desc

    val genInputsStruct = U.genInputsStruct
    val genDefinedInpStruct = U.genDefinedInpStruct

  (* translate an API type to the C types used to represent it in the external API *)
    val trType = CodeGenUtil.trAPIType

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

  (* world pointer *)
    val wrldV = CL.mkVar "wrld"

  (* an l-value expression for accessing a global variable *)
    fun global gv = CL.mkIndirect(CL.mkIndirect(CL.mkVar "wrld", "globals"), GVar.name gv)

  (* generate code to initialize the global input variables from the command-line inputs *)
    fun genInitInputs (env, inputs) = let
        (* the world pointer type *)
          val worldPtrTy = RN.worldPtrTy
        (* the global state pointer type *)
          val globPtrTy = RN.globalPtrTy
        (* the inputs pointer type *)
          val optionsPtrTy = RN.optionsPtrTy env
        (* some common variables *)
          val inpV = CL.mkVar "inp"
          val optsV = CL.mkVar "opts"
        (* initialize a given input global; for sequences and images, this requires
         * loading the value from the specified nrrd file, while for other types
         * we just copy the values.
         *)
          fun initInput ((gv, name, desc, optDflt), stms) = (case GVar.ty gv
                 of Ty.SeqTy(elemTy, NONE) => let
                      val (loadFn, nDims, dims) = (case elemTy
                             of Ty.BoolTy => ("diderot::load_dynseq<bool>", CL.mkInt 0, CL.mkInt 0)
                              | Ty.IntTy => ("Diderot_DynSeqLoadIntFromFile", CL.mkInt 0, CL.mkInt 0)
                              | Ty.TensorTy[] => ("Diderot_DynSeqLoadRealFromFile", CL.mkInt 0, CL.mkInt 0)
                              | Ty.TensorTy _ => raise Fail "TODO: sequences of tensors"
                              | Ty.SeqTy elemTy => raise Fail "TODO: sequences of sequences"
                              | _ => raise Fail "unsupported dynamic sequence type"
                            (* end case *))
                      in
                        CL.mkAssign(global gv,
                          CL.mkApply(loadFn, [wrldV, CL.mkIndirect(inpV, GVar.name gv), nDims, dims])) ::
                        CL.mkIfThen(CL.mkBinOp(global gv, CL.#==, CL.mkInt 0),
                          CL.mkReturn(SOME(CL.mkVar "true"))) :: stms
                      end
                  | Ty.ImageTy(dim, _) => let
                      val loadFn = (case dim
                             of 1 => "Diderot_LoadImage1D"
                              | 2 => "Diderot_LoadImage2D"
                              | 3 => "Diderot_LoadImage3D"
                              | _ => raise Fail "image with dimension > 3"
                            (* end case *))
                      in
                        CL.mkIfThen(
                          CL.mkApply(loadFn, [wrldV, CL.mkIndirect(inpV, GVar.name gv), CL.mkAddrOf(global gv)]),
                          CL.mkReturn(SOME(CL.mkVar "true"))) :: stms
                      end
                  | ty => TrTy.copyFromC{ty=ty, dst=global gv, src=CL.mkIndirect(inpV, GVar.name gv)} @ stms
                (* end case *))
          in
            CL.D_Func(
              ["static"], CL.boolTy, N.initInputs,
              [CL.PARAM([], worldPtrTy, "wrld"), CL.PARAM([], optionsPtrTy, "inp")],
              CL.mkBlock(
                CL.mkDeclInit(globPtrTy, RN.globalsVar, CL.mkIndirect(CL.mkVar "wrld", "_globals")) ::
                List.foldr initInput [CL.mkReturn(SOME(CL.mkVar "false"))] inputs))
          end

  (* generate the functions that handle inputs for standalone executables.  These are:
   *    InitDefaults    -- called to initialize the default input values
   *    RegisterInputs  -- called to register the command-line options for the input globals
   *    InitInputs      -- called to initialize the input globals from the values specified
   *                       on the command line.
   *)
    fun genExecInputFuns (_, []) = []
      | genExecInputFuns arg = U.genExecInputFuns arg @ [genInitInputs arg]

    fun genCheckInputs (env, inputs) = let
        (* the world pointer type *)
          val worldPtrTy = N.worldPtrTy env
          val wrldParam = CL.PARAM([], worldPtrTy, "wrld")
        (* check that the specified input has been defined and, if not, define it to its default *)
          fun check (gv, name, _, optDflt) = let
                val dfltStm = (case optDflt
                       of SOME v => let
                          (* get default file name for images and sequences *)
                            fun getName () = (case v
                                   of IR.E_Lit(Literal.String s) => CL.mkStr s
                                    | _ => raise Fail "expected string for default nrrd"
                                  (* end case *))
                            in
                              case (GVar.ty gv)
                               of Ty.SeqTy(elemTy, NONE) =>
                                    GenLoadNrrd.loadSeqFromFile (global gv, elemTy, getName())
                                | Ty.ImageTy info =>
                                    GenLoadNrrd.loadImage (global gv, info, getName())
                                | _ => CL.mkBlock(ToC.trAssign(ToC.empty, global gv, v))
                              (* end case *)
                            end
                        | NONE => CL.mkBlock[
                              World.errorMsgAdd(CL.mkStr(concat["undefined input \"", name, "\"\n"])),
                              CL.mkReturn(SOME(CL.mkBool true))
                            ]
                      (* end case *))
                in
                  CL.mkIfThen(CL.mkUnOp(CL.%!, U.defined gv), dfltStm)
                end
          in
            CL.D_Func(
              ["static"], CL.boolTy, N.checkDefined env,
              [wrldParam],
              CL.mkBlock(List.map check inputs @ [CL.mkReturn(SOME(CL.mkBool false))]))
          end

  (* for each input variable we generate two or three top-level declarations in the
   * exported API.
   *)
    fun genInputFuns (_, []) = []
      | genInputFuns (env, inputs) = let
        (* the world pointer type *)
          val worldPtrTy = RN.worldPtrTy
          val wrldParam = CL.PARAM([], worldPtrTy, "wrld")
        (* create decls for an input variable *)
          fun mkInputDecls (gv, name, desc, optDflt) = let
                val ty = GVar.ty gv
              (* create a description declaration for the input variable *)
                val descDcl = (case desc
                       of SOME desc => [
                              CL.D_Var([], CL.T_Ptr(CL.T_Named "const char"),
                                N.inputDesc(env, name),
                                SOME(CL.I_Exp(CL.mkStr desc)))
                            ]
                        | NONE => []
                      (* end case *))
                val getDcl = if (Option.isSome optDflt)
                        then let
                          val getName = N.inputGet(env, name)
                        (* generate code for a function that returns the current value of
                         * an input global.
                         *)
                          fun mkFunc outTy = CL.D_Func([], CL.voidTy, getName,
                                [wrldParam, CL.PARAM([], outTy, "v")],
                                CL.mkBlock(TrTy.copyToC{
                                    ty = ty,
                                    dst = (case outTy
                                         of CL.T_Ptr _ => CL.mkUnOp(CL.%*, CL.mkVar "v")
                                          | CL.T_Array _ => CL.mkVar "v"
                                          | _ => raise Fail "not l-value type"
                                        (* end cade *)),
                                    src = global gv
                                  }))
(* FIXME: for images and sequences, it is not clear what the get function should return.
 * For now, we just return 0
 *)
                        (* for images and sequences, we currently return 0 *)
                          fun nrrdFunc () = CL.D_Func([], CL.voidTy, getName,
                                [wrldParam, CL.PARAM([], CL.T_Ptr CL.voidPtr, "v")],
                                CL.mkAssign(CL.mkUnOp(CL.%*, CL.mkVar "v"), CL.mkInt 0))
                          val func = (case ty
                                 of Ty.BoolTy => mkFunc(CL.T_Ptr(trType(env, ty)))
                                  | Ty.StringTy => mkFunc(CL.T_Ptr(trType(env, ty)))
                                  | Ty.IntTy => mkFunc(CL.T_Ptr(trType(env, ty)))
                                  | Ty.TensorTy[] => mkFunc(CL.T_Ptr(trType(env, ty)))
                                  | Ty.TensorTy _ => mkFunc(trType(env, ty))
                                  | Ty.SeqTy(_, SOME _) => mkFunc(trType(env, ty))
                                  | Ty.SeqTy(_, NONE) => nrrdFunc ()
                                  | Ty.ImageTy _ => nrrdFunc ()
                                  | _ => raise Fail(concat["bogus input type ", Ty.toString ty])
                                (* end case *))
                          in
                            [func]
                          end
                        else []
                val setDcl = (case ty
                       of Ty.ImageTy info => [
                              CL.D_Func(
                                [], CL.boolTy, N.inputSetByName(env, name),
                                [wrldParam, CL.PARAM(["const"], CL.charPtr, "s")],
                                CL.appendStm(
                                  GenLoadNrrd.loadImage (global gv, info, CL.mkVar "s"),
                                  CL.mkReturn(SOME(CL.mkBool false)))),
                              CL.D_Func(
                                [], CL.boolTy, N.inputSet(env, name),
                                [wrldParam, CL.PARAM([], nrrdPtrTy, "nin")],
                                CL.appendStm(
                                  GenLoadNrrd.setImage (global gv, info, CL.mkVar "nin"),
                                  CL.mkReturn(SOME(CL.mkBool false))))
                            ]
                        | Ty.SeqTy(elemTy, NONE) => [
                              CL.D_Func(
                                [], CL.boolTy, N.inputSetByName(env, name),
                                [wrldParam, CL.PARAM(["const"], CL.charPtr, "s")],
                                CL.appendStm(
                                  GenLoadNrrd.loadSeqFromFile (global gv, elemTy, CL.mkVar "s"),
                                  CL.mkReturn(SOME(CL.mkBool false)))),
                              CL.D_Func(
                                [], CL.boolTy, N.inputSet(env, name),
                                [wrldParam, CL.PARAM([], nrrdPtrTy, "nin")],
                                CL.appendStm(
                                  GenLoadNrrd.loadSeq (global gv, elemTy, CL.mkVar "nin"),
                                  CL.mkReturn(SOME(CL.mkBool false))))
                            ]
                        | _ => [
                              CL.D_Func(
                                [], CL.boolTy, N.inputSet(env, name),
                                [wrldParam, CL.PARAM([], trType(env, ty), "v")],
                                CL.mkBlock(
                                  CL.mkAssign(U.defined gv, CL.mkBool true) ::
                                  TrTy.copyFromC{ty=ty, dst=global gv, src=CL.mkVar "v"} @
                                    [CL.mkReturn(SOME(CL.mkVar "false"))]))
                            ]
                      (* end case *))
                in
                  (descDcl @ getDcl @ setDcl)
                end
          val extras = [
                  genCheckInputs (env, inputs),
                  U.genDefineInp (env, inputs)
                ]
          in
            List.foldr (fn (input, dcls) => mkInputDecls input @ dcls) extras inputs
          end

  end

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