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

SCM Repository

[diderot] View of /branches/vis15/src/compiler/codegen/gen-library-interface.sml
ViewVC logotype

View of /branches/vis15/src/compiler/codegen/gen-library-interface.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3937 - (download) (annotate)
Mon Jun 6 13:16:10 2016 UTC (2 years, 11 months ago) by jhr
File size: 7650 byte(s)
  Working on merge: FIXMEs
(* gen-library-interface.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 the C header file for the library produced by the compiler.
 *
 * The format of header file is:
 *
 *      HEAD
 *      decls for input variables
 *      BODY
 *      decls for output variables
 *      FOOT
 *)

structure GenLibraryInterface : sig

    val gen : {
            env : CodeGenEnv.t,                 (* target information *)
            rt : string option,                 (* fragment with extra runtime system hooks *)
            inputs : TreeGlobalVar.t Inputs.input list,
            outputs : (APITypes.t * string) list
          } -> unit

  (* standard names and types used in the library interface *)
    val inputDesc      : TargetSpec.t * string -> string
    val inputGet       : TargetSpec.t * string -> string
    val inputSet       : TargetSpec.t * string -> string
    val inputSetByName : TargetSpec.t * string -> string
    val snapshotGet    : TargetSpec.t * string -> string
    val outputGet      : TargetSpec.t * string -> string
    val worldTy        : TargetSpec.t -> string

  end = struct

    structure Ty = APITypes
    structure CL = CLang
    structure Spec = TargetSpec
    structure Env = CodeGenEnv
    structure Out = CodeOutput

    val openOut = Out.openOut {ext = "h", ppDecl = PrintAsC.output}

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

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

    fun mkSymbol base = let
          fun tr c = if Char.isAlpha c then Char.toUpper c
                else if Char.isDigit c then c
                else #"_"
          in
            String.concat["_", CharVector.map tr base, "_H_"]
          end

  (* standard names and types used in the library interface *)
    val inputDesc      = TargetSpec.qualifyCId' "input_desc"
    val inputGet       = TargetSpec.qualifyCId' "input_get"
    val inputSet       = TargetSpec.qualifyCId' "input_set"
    val inputSetByName = TargetSpec.qualifyCId' "input_set_by_name"
    val snapshotGet    = TargetSpec.qualifyCId' "snapshot"
    val outputGet      = TargetSpec.qualifyCId' "output_get"
    val worldTy        = TargetSpec.qualifyCId "world_t"

    fun gen {env, rt, inputs, outputs} = let
	  val spec = Env.target env
          val filename = OS.Path.joinDirFile{
                  dir = #outDir spec,
                  file = OS.Path.joinBaseExt{base = #outBase spec, ext = SOME "h"}
                }
        (* the world pointer type *)
          val worldPtrTy = CL.T_Ptr(CL.T_Named(worldTy spec))
        (* create decls for an input variable *)
          fun mkInputDecls (Inputs.INP{var, name, ty,  desc, init}) = let
                val wrldParam = CL.PARAM([], worldPtrTy, "wrld")
              (* create a description declaration for the input variable *)
                val descDcl = (case desc
                       of NONE => []
                        | SOME desc => [
                              CL.D_Var(["extern"], CL.T_Ptr(CL.T_Named "const char"),
                                inputDesc(spec, name), NONE)
                            ]
                      (* end case *))
                val getDcl = (case init
		       of Inputs.NoDefault => []
			| _ => let
			    val name = inputGet(spec, name)
			  (* convert the input type to a by-reference C type *)
			    val outTy = (case ty
				   of Ty.BoolTy => CL.T_Ptr(trType(env, ty))
				    | Ty.StringTy => CL.T_Ptr(trType(env, ty))
				    | Ty.IntTy => CL.T_Ptr(trType(env, ty))
				    | Ty.TensorTy[] => CL.T_Ptr(trType(env, ty))
				    | Ty.TensorTy _=> trType(env, ty)
				    | Ty.SeqTy(_, SOME _) => trType(env, ty)
(* QUESTION: for images and sequences, it is not clear what the get function should return.
 * For now, we just return 0
 *)
				    | Ty.SeqTy(_, NONE) => CL.T_Ptr CL.voidPtr
				    | Ty.ImageTy _ => CL.T_Ptr CL.voidPtr
				  (* end case *))
			    in [
			      CL.D_Proto([], CL.voidTy, name, [wrldParam, CL.PARAM([], outTy, "v")])
			    ] end
		      (* end case *))
                val setDcl = let
                    (* prototypes for setting an image or dynamic sequence from a nrrd *)
                      fun loadPrototypes () = [
                              CL.D_Proto(
                                [], CL.boolTy, inputSetByName(spec, name),
                                [wrldParam, CL.PARAM(["const"], CL.charPtr, "s")]),
                              CL.D_Proto(
                                [], CL.boolTy, inputSet(spec, name),
                                [wrldParam, CL.PARAM([], nrrdPtrTy, "data")])
                            ]
                      in
                        case ty
                         of Ty.ImageTy _ => loadPrototypes()
                          | Ty.SeqTy(_, NONE) => loadPrototypes()
                          | _ => [
                                CL.D_Proto(
                                  [], CL.boolTy, inputSet(spec, name),
                                  [wrldParam, CL.PARAM([], trType(env, ty), "v")])
                              ]
                        (* end case *)
                      end
                in
                  descDcl @ getDcl @ setDcl
                end
        (* create a decl for an output variable *)
          fun mkGetDecl snapshot (Ty.SeqTy(_, NONE), name) = [
                  CL.D_Proto(
                    [], CL.boolTy, (if snapshot then snapshotGet else outputGet)(spec, name),
                    [CL.PARAM([], worldPtrTy, "wrld"), CL.PARAM([], nrrdPtrTy, "lengths"), CL.PARAM([], nrrdPtrTy, "data")])
                ]
            | mkGetDecl snapshot (_, name) = [
                  CL.D_Proto(
                    [], CL.boolTy, (if snapshot then snapshotGet else outputGet)(spec, name),
                    [CL.PARAM([], worldPtrTy, "wrld"), CL.PARAM([], nrrdPtrTy, "data")])
                ]
          val outS = openOut filename
(* NOTE: there is some redundancy between placeholders and the substitutions defined in the target files *)
          val placeholders = [
                  ("DIDEROTC_CMD", #diderotc spec),
                  ("DIDEROTC_ARGV", String.concatWith " " (#argv spec)),
                  ("DIDEROTC_VERSION", #version spec),
                  ("DIDEROT_FLOAT_PRECISION", Spec.floatPrecisionDef spec),
                  ("DIDEROT_INT_PRECISION", Spec.intPrecisionDef spec),
                  ("DIDEROT_TARGET", Spec.targetDef spec),
                  ("HDRFILE", Out.filename outS),
                  ("HDR_DEFINE", mkSymbol(#outBase spec)),
                  ("PREFIX", #namespace spec),
                  ("SRCFILE", #srcFile spec)
                ]
	  val prDecl = Out.decl outS
	  val prFrag = Out.fragment placeholders outS
          val prDecls = List.app prDecl
          in
            prFrag Fragments.libHHead;
            prDecl (CL.D_Verbatim ["\n/**** Functions etc. for input variables ****/\n"]);
            List.app (fn input => prDecls (mkInputDecls input)) inputs;
            case rt of SOME rt => prFrag rt | _ => ();
            prFrag Fragments.libHBody;
            prDecl (CL.D_Verbatim ["\n/**** Getters for output values ****/\n"]);
            if (#snapshot spec)
              then List.app (fn output => prDecls (mkGetDecl true output)) outputs
              else ();
            List.app (fn output => prDecls (mkGetDecl false output)) outputs;
            prFrag Fragments.libHFoot;
            Out.closeOut outS
          end

  end

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