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 3931 - (download) (annotate)
Sun Jun 5 14:13:21 2016 UTC (3 years, 2 months ago) by jhr
File size: 6623 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.qname var)
                  | Ty.ImageTy _ => (CL.charPtr, GVar.qname var)
                  | ty => (trType(env, ty), GVar.qname var)
                (* end case *))
          in
            [CL.D_StructDef(NONE, List.map mkField inputs, SOME RN.inputsTyName)]
          end

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

  (* generate code to register command-line options for setting the input variables *)
    fun genRegisterInputs (env, inputs) = let
	(* pointer to the inputs *)
	  val inputsV = "inp"
	  val inputsE = CL.mkVar inputsV
        (* the options pointer type *)
          val optionsPtrTy = CL.T_Ptr (Env.optionsTy env)
        (* some common variables *)
          val optsV = CL.mkVar "opts"
        (* register a given input *)
          fun registerInput (Inp.INP{var, name, ty, desc, init}) = let
		val args = [case init of Inp.NoDefault => CL.mkBool false | _ => CL.mkBool true]
		val args = let
		      fun arrayArg n = CL.mkInt(IntLit.fromInt n) ::
			    CL.mkIndirect(inputsE, GVar.qname var) :: args
		      in
			case ty
			 of Ty.TensorTy(shape as _::_) => arrayArg (List.foldl Int.* 1 shape)
			  | Ty.SeqTy(_, SOME n) => arrayArg n
			  | _ => CL.mkAddrOf(CL.mkIndirect(inputsE, GVar.qname var)) :: args
			(* end case *)
		      end
		val args = (case desc
			of NONE => CL.mkVar "nullptr" :: args
		         | SOME s => CL.mkStr s :: args
		       (* end case *))
		val args = CL.mkStr name :: args
		in
		  CL.mkExpStm (CL.mkIndirectDispatch (optsV, "add", args))
                end
          in
            CL.D_Func(
              ["static"], CL.voidTy, "register_inputs",
              [CL.PARAM([], RN.inputsPtrTy, inputsV), 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.qname 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