-- | Compiler stages.---- A compiler stage is a sequence of standard transformations.-- Each of the individual transformations are expressed as a pipeline from -- "DDC.Build.Pipeline". The stages here run several pipelines each,-- and contain the code that can dump the intermediate program after-- each transformation.--moduleDDC.Driver.Stage(Config(..),ViaBackend(..)-- * Lite stages,stageLiteLoad,stageLiteOpt,stageLiteToSalt-- * Salt stages,stageSaltOpt,stageSaltToC,stageSaltToLLVM,stageCompileSalt-- * LLVM stages,stageCompileLLVM)whereimportDDC.Driver.SourceimportDDC.Build.BuilderimportDDC.Build.PipelineimportDDC.Core.Transform.NamifyimportDDC.Core.Simplifier(Simplifier)importSystem.FilePathimportData.MaybeimportqualifiedDDC.Core.Simplifier.RecipeasSimportqualifiedDDC.Build.Language.SaltasSaltimportqualifiedDDC.Build.Language.LiteasLiteimportqualifiedDDC.Core.LiteasLiteimportqualifiedDDC.Core.Salt.NameasSaltimportqualifiedDDC.Core.Salt.RuntimeasSalt-- | Configuration for main compiler stages.dataConfig=Config{-- | Dump intermediate code.configDump::Bool-- | Simplifiers to apply to intermediate code,configSimplLite::SimplifierInt()Lite.Name,configSimplSalt::SimplifierInt()Salt.Name-- | Backend code generator to use,configViaBackend::ViaBackend-- | Runtime system configuration,configRuntime::Salt.Config-- | The builder to use for the target architecture,configBuilder::Builder-- | Suppress imports in Core modules,configSuppressCoreImports::Bool-- | Suppress the #import prelude in C modules,configSuppressHashImports::Bool-- | Override output file,configOutputFile::MaybeFilePath-- | Override directory for build products,configOutputDir::MaybeFilePath-- | Keep intermediate .ddc.ll files,configKeepLlvmFiles::Bool-- | Keep intermediate .ddc.c files,configKeepSeaFiles::Bool-- | Keep intermediate .ddc.s files,configKeepAsmFiles::Bool}dataViaBackend-- | Compile via the C backend.=ViaC-- | Compile via the LLVM backend.|ViaLLVMderivingShow--------------------------------------------------------------------------------- | Type check Core Lite.stageLiteLoad::Config->Source->[PipeCore()Lite.Name]->PipeTextLite.NameLite.ErrorstageLiteLoadconfigsourcepipesLite=PipeTextLoadCoreLite.fragment[PipeCoreStrip(PipeCoreOutput(dumpconfigsource"dump.lite.dcl"):pipesLite)]--------------------------------------------------------------------------------- | Optimise Core Lite.stageLiteOpt::Config->Source->[PipeCore()Lite.Name]->PipeCore()Lite.NamestageLiteOptconfigsourcepipes=PipeCoreSimplifyLite.fragment(0::Int)(configSimplLiteconfig)(PipeCoreOutput(dumpconfigsource"dump.lite-opt.dcl"):pipes)--------------------------------------------------------------------------------- | Optimise Core Salt.stageSaltOpt::Config->Source->[PipeCore()Salt.Name]->PipeCore()Salt.NamestageSaltOptconfigsourcepipes=PipeCoreSimplifySalt.fragment(0::Int)(configSimplSaltconfig)(PipeCoreOutput(dumpconfigsource"dump.salt-opt.dcl"):pipes)--------------------------------------------------------------------------------- | Convert Core Lite to Core Salt.----- The Lite to Salt transform requires the program to be normalised,-- and have type annotations.stageLiteToSalt::Config->Source->[PipeCore()Salt.Name]->PipeCore()Lite.NamestageLiteToSaltconfigsourcepipesSalt=PipeCoreSimplifyLite.fragment0normalizeLite[PipeCoreCheckLite.fragment[PipeCoreOutput(dumpconfigsource"dump.lite-normalized.dcl"),PipeCoreAsLite[PipeLiteToSalt(buildSpec$configBuilderconfig)(configRuntimeconfig)(PipeCoreOutput(dumpconfigsource"dump.salt.dcs"):pipesSalt)]]]wherenormalizeLite=S.anormalize(makeNamifierLite.freshT)(makeNamifierLite.freshX)--------------------------------------------------------------------------------- | Convert Core Salt to C code.stageSaltToC::Config->Source->Sink->PipeCore()Salt.NamestageSaltToCconfigsourcesink=PipeCoreSimplifySalt.fragment0normalizeSalt[PipeCoreCheckSalt.fragment[PipeCoreOutput(dumpconfigsource"dump.salt-normalized.dcs"),PipeCoreAsSalt[PipeSaltTransfer[PipeSaltOutput(dumpconfigsource"dump.salt-transfer.dcs"),PipeSaltPrint(not$configSuppressHashImportsconfig)(buildSpec$configBuilderconfig)sink]]]]wherenormalizeSalt=S.anormalize(makeNamifierSalt.freshT)(makeNamifierSalt.freshX)--------------------------------------------------------------------------------- | Compile Core Salt via C code.stageCompileSalt::Config->Source->FilePath-- ^ Path of original source file.-- Build products are placed into the same dir.->Bool-- ^ Should we link this into an executable->PipeCore()Salt.NamestageCompileSaltconfigsourcefilePathshouldLinkExe=let-- Decide where to place the build products.outputDir=fromMaybe(takeDirectoryfilePath)(configOutputDirconfig)outputDirBase=dropExtension(replaceDirectoryfilePathoutputDir)cPath=outputDirBase++".ddc.c"oPath=outputDirBase++".o"exePathDefault=outputDirBaseexePath=fromMaybeexePathDefault(configOutputFileconfig)inPipeCoreSimplifySalt.fragment0normalizeSalt[PipeCoreCheckSalt.fragment[PipeCoreOutput(dumpconfigsource"dump.salt-normalized.dcs"),PipeCoreAsSalt[PipeSaltTransfer[PipeSaltOutput(dumpconfigsource"dump.salt-transfer.dcs"),PipeSaltCompile(buildSpec$configBuilderconfig)(configBuilderconfig)cPathoPath(ifshouldLinkExethenJustexePathelseNothing)(configKeepSeaFilesconfig)]]]]wherenormalizeSalt=S.anormalize(makeNamifierSalt.freshT)(makeNamifierSalt.freshX)--------------------------------------------------------------------------------- | Convert Core Salt to LLVM.stageSaltToLLVM::Config->Source->[PipeLlvm]->PipeCore()Salt.NamestageSaltToLLVMconfigsourcepipesLLVM=PipeCoreSimplifySalt.fragment0normalizeSalt[PipeCoreCheckSalt.fragment[PipeCoreOutput(dumpconfigsource"dump.salt-normalized.dcs"),PipeCoreAsSalt[PipeSaltTransfer[PipeSaltOutput(dumpconfigsource"dump.salt-transfer.dcs"),PipeSaltToLlvm(buildSpec$configBuilderconfig)pipesLLVM]]]]wherenormalizeSalt=S.anormalize(makeNamifierSalt.freshT)(makeNamifierSalt.freshX)--------------------------------------------------------------------------------- | Compile LLVM code.stageCompileLLVM::Config->Source->FilePath-- ^ Path of original source file.-- Build products are placed into the same dir.->Bool-- ^ Should we link this into an executable->PipeLlvmstageCompileLLVMconfig_sourcefilePathshouldLinkExe=let-- Decide where to place the build products.outputDir=fromMaybe(takeDirectoryfilePath)(configOutputDirconfig)outputDirBase=dropExtension(replaceDirectoryfilePathoutputDir)llPath=outputDirBase++".ddc.ll"sPath=outputDirBase++".ddc.s"oPath=outputDirBase++".o"exePathDefault=outputDirBaseexePath=fromMaybeexePathDefault(configOutputFileconfig)in-- Make the pipeline for the final compilation.PipeLlvmCompile{pipeBuilder=configBuilderconfig,pipeFileLlvm=llPath,pipeFileAsm=sPath,pipeFileObject=oPath,pipeFileExe=ifshouldLinkExethenJustexePathelseNothing,pipeKeepLlvmFiles=configKeepLlvmFilesconfig,pipeKeepAsmFiles=configKeepAsmFilesconfig}-------------------------------------------------------------------------------- | If the Dump mode is set -- then produce a SinkFile to write a module to a file, -- otherwise produce SinkDiscard to drop it on the floor.dump::Config->Source->String->SinkdumpconfigsourcedumpFile|configDumpconfig=letoutputDir|SourceFilefilePath<-source=fromMaybe(takeDirectoryfilePath)(configOutputDirconfig)|otherwise=fromMaybe"."(configOutputDirconfig)inSinkFile$outputDir</>dumpFile|otherwise=SinkDiscard