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-inputs-util.sml
ViewVC logotype

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3912 - (download) (annotate)
Wed May 25 14:53:50 2016 UTC (3 years ago) by jhr
File size: 6268 byte(s)
  Working on merge: code generation
(* gen-inputs-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.
 *)

structure GenInputsUtil : sig

    type input_desc = TreeGlobalVar.t Inputs.input

  (*** 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 common functions that handle inputs for standalone executables.  These are:
   *    init_defaults    -- called to initialize the default input values
   *    register_inputs  -- called to register the command-line options for the input globals
   *)
    val genExecInputFuns : CodeGenEnv.t * TreeIR.program -> CLang.decl list

  (*** Support for libraries ***)

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

  (* generate the function that initializes the defined-input flag struct. *)
    val genDefineInp : input_desc list -> CLang.decl

  (*** Utility functions ***)

  (* generate code to copy a value *)
    val copy : {env : CodeGenEnv.t, ty : APITypes.t, src : CLang.exp, dst : CLang.exp} -> CLang.stm

  (* an l-value expression for accessing a defined-input flag for the given global input *)
    val defined : TreeGlobalVar.t -> CLang.exp

  end = struct

    structure IR = TreeIR
    structure Ty = APITypes
    structure GVar = TreeGlobalVar
    structure CL = CLang
    structure ToC = TreeToCxx
    structure Env = CodeGenEnv
    structure Inp = Inputs
    structure RN = CxxNames

    type input_desc = GVar.t Inp.input

    val worldPtrTy = RN.worldPtrTy
    val globalPtrTy = RN.globalPtrTy

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

  (* generate the input initialization structure that we use to initialize input
   * globals from command-line arguments in stand-alone executables.
   *)
    fun genInputsStruct (_, []) = []
      | genInputsStruct (env : Env.t, inputs) = let
          fun mkField (Inp.INP{var, ty, ...}) = (case ty
                 of Ty.SeqTy(_, NONE) => (CL.charPtr, GVar.name var)
                  | Ty.ImageTy _ => (CL.charPtr, GVar.name var)
                  | ty => (trType(env, ty), GVar.name var)
                (* end case *))
          in
            [CL.D_StructDef(NONE, List.map mkField inputs, SOME "cmd_line_inputs")]
          end

  (* generate code to initialize the default input values *)
    fun genInitDefaults (env, constInit) =
	  CL.D_Func(
	    ["static"], CL.voidTy, "init_defaults",
	    [CL.PARAM([], globalPtrTy, Env.global env)],
	    ToC.trBlock (env, constInit))

  (* generate code to register command-line options for setting the input variables *)
    fun genRegisterInputs (env, inputs) = let
	(* pointer to the globals *)
	  val globalsV = Env.global env
	  val globalsE = CL.mkVar globalsV
        (* the options pointer type *)
          val optionsPtrTy = CL.T_Ptr (Env.optionsTy env)
        (* some common variables *)
          val inpV = CL.mkVar "inp"
          val optsV = CL.mkVar "opts"
        (* register a given input *)
          fun registerInput (Inp.INP{var, name, ty, desc, init}) =
		CL.mkCallExp(
		  CL.mkIndirect(optsV, "add"),
		  [ CL.mkStr name,
		    CL.mkStr(Option.getOpt(desc, "")),
		    if Ty.isCArrayTy ty
		      then CL.mkIndirect(globalsE, GVar.name var)
		      else CL.mkAddrOf(CL.mkIndirect(globalsE, GVar.name var)),
		    case init of Inp.NoDefault => CL.mkBool false | _ => CL.mkBool true
		  ])
          in
            CL.D_Func(
              ["static"], CL.voidTy, "register_inputs",
              [CL.PARAM([], globalPtrTy, globalsV), CL.PARAM([], RN.optionsPtrTy env, "opts")],
              CL.mkBlock(List.map registerInput inputs))
          end

  (* generate the common functions that handle inputs for standalone executables.  These are:
   *    init_defaults    -- called to initialize the default input values
   *    register_inputs  -- called to register the command-line options for the input globals
   *)
    fun genExecInputFuns (env, IR.Program{inputs, constInit, ...}) = [
            genInitDefaults (env, constInit),
            genRegisterInputs (env, inputs)
          ]

  (* an l-value expression for accessing a defined-input flag *)
    fun defined gv = CL.mkSelect(CL.mkIndirect(CL.mkVar "wrld", "definedInp"), GVar.name gv)

  (* generate the typedef for the defined-input flag struct. *)
    fun genDefinedInpStruct [] = []
      | genDefinedInpStruct inputs = let
          fun mkField (Inp.INP{var, ...}) = (CL.boolTy, GVar.name var)
          in
            [CL.D_StructDef(NONE, List.map mkField inputs, SOME "defined_inputs")]
          end

  (* generate the function that initializes the defined-input flag struct. *)
    fun genDefineInp inputs = let
        (* the world pointer type *)
          val wrldParam = CL.PARAM([], worldPtrTy, "wrld")
          fun initFlag (Inp.INP{var, ...}) = CL.mkAssign(defined var, CL.mkBool false)
          in
            CL.D_Func(
              ["static"], CL.voidTy, "init_defined_inputs",
              [wrldParam],
              CL.mkBlock(List.map initFlag inputs))
          end

  (* generate code to copy a value *)
    fun copy {env, ty, src, dst} = let
          fun assign () = CL.mkAssign(dst, src)
	  fun addrOf (CL.E_UnOp(CL.%*, x)) = x
            | addrOf x = CL.mkUnOp(CL.%&, x)
          fun memcpy () =
		CL.mkCall("std::memcpy", [addrOf dst, addrOf src, CL.mkSizeof(trType(env, ty))])
	  in
	    case ty
	     of Ty.IntTy => assign ()
	      | Ty.BoolTy => assign ()
	      | Ty.TensorTy[] => assign ()
	      | Ty.TensorTy shp => memcpy()
(* FIXME: here we probably need to deal with a conversion between "char *" and "std::string" *)
	      | Ty.StringTy => raise Fail "FIXME: copy string"
	      | Ty.ImageTy _ => raise Fail "unexpected image copy"
	      | Ty.SeqTy(_, SOME _) => memcpy()
	      | Ty.SeqTy(_, NONE) => raise Fail "unexpected dynamic sequence copy"
	    (* end case *)
	  end

  end

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