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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3962 - (download) (annotate)
Mon Jun 13 16:45:17 2016 UTC (3 years, 3 months ago) by jhr
File size: 9440 byte(s)
working on merge: code generation
(* gen.sml
 *
 * Code generation for the sequential and parallel targets.
 *
 * COPYRIGHT (c) 2016 The Diderot Project (http://diderot-language.cs.uchicago.edu)
 * All rights reserved.
 *)

structure Gen : sig

    val exec : TargetSpec.t * TreeIR.program -> unit

    val library : TargetSpec.t * TreeIR.program -> unit

  end = struct

    structure IR = TreeIR
    structure GV = TreeGlobalVar
    structure CL = CLang
    structure Env = CodeGenEnv
    structure Out = CodeOutput
    structure RN = CxxNames

    val openCxxOut = Out.openOut {ext = "cxx", ppDecl = PrintAsCxx.output}

    fun mkEnv spec = if TargetSpec.dualState spec
	  then Env.new {
	      global = RN.globalsVar,
	      selfIn = RN.selfInVar,
	      selfOut = RN.selfOutVar,
	      spec = spec
	    }
	  else Env.new {
	      global = RN.globalsVar,
	      selfIn = RN.selfVar,
	      selfOut = RN.selfVar,
	      spec = spec
	    }

  (* create the target-specific substitution list *)
    fun mkSubs (spec, strand, IR.Create{dim, ...}) = let
	  val IR.Strand{name, stateInit, initM, updateM, stabilizeM, ...} = strand
	  fun mkMethodArgs (name, NONE) = (name, "")
	    | mkMethodArgs (name, SOME(IR.Method{usesGlobals, needsWorld, ...})) = let
		val value = if needsWorld then "this, " else ""
		val value = if usesGlobals then value ^ "glob, " else value
		in
		  (name, value)
		end
	  in [
	    ("CFILE",			OS.Path.joinBaseExt{base= #outBase spec, ext= SOME "c"}),
	    ("CXXFILE",			OS.Path.joinBaseExt{base= #outBase spec, ext= SOME "cxx"}),
	    ("HDRFILE",			OS.Path.joinBaseExt{base= #outBase spec, ext= SOME "h"}),
	    ("PREFIX",			#namespace spec),
	    ("SRCFILE",			#srcFile spec),
	    ("PROG_NAME",		#outBase spec),
	    ("STRAND",			Atom.toString name),
	    ("STRANDTY",		Atom.toString name ^ "_strand"),
	    ("IS_GRID",			Bool.toString(#isGrid spec)),
	    ("NUM_AXES",		Int.toString(Option.getOpt(dim, 1))),
	    ("DIDEROTC_CMD",		#diderotc spec),
	    ("DIDEROTC_ARGV",		String.concatWith " " (#argv spec)),
	    ("DIDEROTC_VERSION",	#version spec),
	    ("DIDEROT_FLOAT_PRECISION",	TargetSpec.floatPrecisionDef spec),
	    ("DIDEROT_INT_PRECISION",	TargetSpec.intPrecisionDef spec),
	    ("DIDEROT_TARGET",		TargetSpec.targetDef spec),
	    ("REALTY",			if #double spec then "double" else "float"),
	    ("INTTY",			if #longint spec then "int64_t" else "int32_t"),
	    mkMethodArgs ("STATE_INIT_ARGS", SOME stateInit),
	    mkMethodArgs ("INITIALLY_ARGS", initM),
	    mkMethodArgs ("UPDATE_ARGS", SOME updateM),
	    mkMethodArgs ("STABILIZE_ARGS", stabilizeM)
	  ] end

    fun condCons (true, x, xs) = x::xs
      | condCons (false, _, xs) = xs

    fun verbFrag (spec, parFrag, seqFrag, subs) =
	  CL.verbatimDcl [if (TargetSpec.isParallel spec) then parFrag else seqFrag] subs

  (* generate the struct declaration for the global variables *)
(* FIXME: what about constants? *)
    fun genGlobalStruct (env, consts, inputs, globals) =
	  if #hasGlobals(Env.target env)
	    then let
	      fun mkField gv = (TreeToCxx.trType(env, GV.ty gv), GV.qname gv)
	      val fields = List.map (mkField o Inputs.varOf) inputs
	      val fields = fields @ List.map mkField globals
	      in
		[CL.D_StructDef(SOME "globals", fields, NONE)]
	      end
	    else []

    fun genInitGlobals (env, IR.Block{locals, body}) = let
	  val env = Env.setExitHandler (env, fn _ => [CL.mkReturn(SOME(CL.mkVar "false"))])
	  val dcl = CL.mkDeclInit(
		RN.globalPtrTy, RN.globalsVar,
		CL.mkIndirect(CL.mkVar RN.worldVar, "_globals"))
	  in
	    CL.D_Func(["static"], CL.boolTy, "init_globals",
	      [RN.worldParam],
	      TreeToCxx.trWithLocals (env, !locals,
		fn env => dcl :: #2(TreeToCxx.trStms(env, body))))
	  end

    fun runFrag (spec, subs) = if TargetSpec.noBSP spec
	    then verbFrag (spec, Fragments.parallelRunNoBSP, Fragments.sequentialRunNoBSP, subs)
	    else verbFrag (spec, Fragments.parallelRun, Fragments.sequentialRun, subs)

    fun compile (spec : TargetSpec.t, basename) = let
	(* generate the C compiler flags *)
	  val cflags = ["-I" ^ Paths.diderotInclude(), "-I" ^ Paths.teemInclude()]
	  val cflags = condCons (TargetSpec.isParallel spec, #pthread Paths.cxxflags, cflags)
	  val cflags = if #debug spec
		then #debug Paths.cxxflags :: cflags
		else #ndebug Paths.cxxflags :: cflags
	  val cflags = #base Paths.cxxflags :: cflags
	  in
	    RunCC.compile (basename, cflags)
	  end

    fun ldFlags (spec : TargetSpec.t) = if #exec spec
	  then let
	    val extraLibs = condCons (TargetSpec.isParallel spec, #pthread Paths.extraLibs, [])
	    val extraLibs = Paths.teemLinkFlags() @ #base Paths.extraLibs :: extraLibs
	    val rtLib = TargetSpec.runtimeLibName spec
	    in
	      condCons (TargetSpec.isParallel spec, #pthread Paths.cxxflags, rtLib :: extraLibs)
	    end
	  else [TargetSpec.runtimeLibName spec]

  (* generate source code that is common to both libraries and standalone executables *)
    fun outputSrc (outS, env, spec, prog, strand, substitutions, genInputCode) = let
	  val IR.Program{
		  consts, inputs, globals, globalInit, create as IR.Create{dim, ...}, ...
		} = prog
	  val IR.Strand{name=strandName, ...} = strand
	  val ppDecl = Out.decl outS
	  val {structDef, methods} = GenStrand.gen (env, strand)
	  val outputs = OutputUtil.gatherOutputs prog
	  in
	    if (TargetSpec.isParallel spec)
	      then ppDecl (CL.verbatimDcl [Fragments.parallelExtras] substitutions)
	      else ();
	    if TargetSpec.dualState spec
	      then ppDecl (CL.D_Verbatim ["#define DIDEROT_DUAL_STATE\n"])
	      else ();
	    if not(#hasGlobals spec)
	      then ppDecl (CL.D_Verbatim ["#define DIDEROT_NO_GLOBALS\n"])
	      else ();
	    if not(#hasInputs spec)
	      then ppDecl (CL.D_Verbatim ["#define DIDEROT_NO_INPUTS\n"])
	      else ();
	    List.app ppDecl (genGlobalStruct (env, consts, inputs, globals));
	    ppDecl structDef;
	    ppDecl (GenWorld.genStruct(spec, strandName, Option.getOpt(dim, 1)));
	    List.app ppDecl (genInputCode());
	    if #hasGlobals spec
	      then ppDecl (genInitGlobals (env, globalInit))
	      else ();
	    List.app ppDecl methods;
	    List.app ppDecl (GenOutputs.gen (env, dim, outputs));
	    ppDecl (CL.verbatimDcl [Fragments.worldMethods] substitutions);
	    ppDecl (GenWorld.genInitiallyFun (env, strandName, create));
	    ppDecl (runFrag (spec, substitutions))
	  end

(********************
        fun outputLibSrc (baseName, prog as Prog{props, inputs, strands, ...}) = let
              val [strand] = AtomTable.listItems strands
              val substitutions = mkSubs (props, strand)
            (* output to C file *)
              val out = openOut baseName
              fun ppDecl dcl = PrintAsC.output(#ppStrm out, dcl)
              in
                ppDecl (CL.verbatimDcl [LibHdrFrag.text] substitutions);
                List.app ppDecl (GenInputs.genDefinedInpStruct (props, !inputs));
                outputSrc (out, prog, strand, substitutions,
                  fn () => GenInputs.genInputFuns(props, !inputs));
                ppDecl (CL.verbatimDcl [CBodyFrag.text] substitutions);
                closeOut out
              end

        fun generateLib (prog as Prog{props, inputs, strands, ...}) = let
              val {outDir, outBase, exec, double, debug, ...} = props
              val basename = OS.Path.joinDirFile{dir=outDir, file=outBase}
              val [Strand{state, output, ...}] = AtomTable.listItems strands
              in
              (* generate the library .h file *)
                GenLibraryInterface.gen {
                    props = props,
                    rt = if TargetSpec.isParallel spec
                      then SOME LibInterfaceParFrag.text
                      else NONE,
                    inputs = !inputs,
                    outputs = output
                  };
              (* *)
                outputLibSrc (basename, prog);
              (* compile and link *)
                compile (props, basename);
                RunCC.linkLib (basename, ldFlags props)
              end
********************)

    fun exec (spec : TargetSpec.t, prog) = let
	  val IR.Program{inputs, strand, create, ...} = prog
	  val env = mkEnv spec
	  val baseName = OS.Path.joinDirFile{dir = #outDir spec, file = #outBase spec}
	  val substitutions = mkSubs (spec, strand, create)
	(* output to C++ file *)
	  val outS = openCxxOut baseName
	  val ppDecl = Out.decl outS
	  val fragment = Out.fragment substitutions outS
	  in
	    GenExecUtil.execHead (outS, substitutions);
	    List.app ppDecl (GenTysAndOps.gen (env, CollectInfo.collect prog));
	    outputSrc (outS, env, spec, prog, strand, substitutions,
	      fn () => (
		GenInputs.genInputsStruct (env, inputs) @
		GenInputs.genExecInputFuns (env, prog) @
		OutputUtil.genRegisterOutputOpts (env, OutputUtil.gatherOutputs prog)));
	    GenExecUtil.execFoot (outS, substitutions);
	  (* generate main function after closing off the namespace *)
	    ppDecl (verbFrag (spec, Fragments.parallelMain, Fragments.sequentialMain, substitutions));
	    Out.closeOut outS;
	    compile (spec, baseName);
	    RunCC.linkExec (baseName, ldFlags spec)
	  end

    fun library (spec : TargetSpec.t, prog) = let
	  val IR.Program{
		  props, target, consts, inputs, constInit,
		  globals, globalInit, strand, create, update
		} = prog
	  val {outDir, outBase, exec, double, debug, ...} = spec
	  val env = mkEnv spec
	  in
	    raise Fail "FIXME"
	  end

  end

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