Index: nkinsfile
===================================================================
--- Jenkinsfile (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ (revision )
@@ -1,514 +1,0 @@
-#!groovy
-
-import groovy.transform.Field
-
-// For skipping stages
-import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
-
-//===========================================================================================================
-// Main loop of the compilation
-//===========================================================================================================
-
-node('master') {
- // Globals
- BuildDir = pwd tmp: true
- SrcDir = pwd tmp: false
- Settings = null
- StageName = ''
-
- // Local variables
- def err = null
- def log_needed = false
-
- currentBuild.result = "SUCCESS"
-
- try {
- //Wrap build to add timestamp to command line
- wrap([$class: 'TimestamperBuildWrapper']) {
-
- Settings = prepare_build()
-
- node(Settings.Architecture.node) {
- BuildDir = pwd tmp: true
- SrcDir = pwd tmp: false
-
- clean()
-
- checkout()
-
- build()
-
- test()
-
- benchmark()
-
- build_doc()
-
- publish()
- }
-
- // Update the build directories when exiting the node
- BuildDir = pwd tmp: true
- SrcDir = pwd tmp: false
- }
- }
-
- //If an exception is caught we need to change the status and remember to
- //attach the build log to the email
- catch (Exception caughtError) {
- //rethrow error later
- err = caughtError
-
- echo err.toString()
-
- //An error has occured, the build log is relevent
- log_needed = true
-
- //Store the result of the build log
- currentBuild.result = "${StageName} FAILURE".trim()
- }
-
- finally {
- //Send email with final results if this is not a full build
- email(log_needed)
-
- echo 'Build Completed'
-
- /* Must re-throw exception to propagate error */
- if (err) {
- throw err
- }
- }
-}
-//===========================================================================================================
-// Main compilation routines
-//===========================================================================================================
-def clean() {
- build_stage('Cleanup', true) {
- // clean the build by wipping the build directory
- dir(BuildDir) {
- deleteDir()
- }
- }
-}
-
-//Compilation script is done here but environnement set-up and error handling is done in main loop
-def checkout() {
- build_stage('Checkout', true) {
- //checkout the source code and clean the repo
- final scmVars = checkout scm
- Settings.GitNewRef = scmVars.GIT_COMMIT
- Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT
-
- echo GitLogMessage()
- }
-}
-
-def build() {
- // build_stage('Build', true) {
- // // Build outside of the src tree to ease cleaning
- // dir (BuildDir) {
- // //Configure the conpilation (Output is not relevant)
- // //Use the current directory as the installation target so nothing escapes the sandbox
- // //Also specify the compiler by hand
- // targets=""
- // if( Settings.RunAllTests || Settings.RunBenchmark ) {
- // targets="--with-target-hosts='host:debug,host:nodebug'"
- // } else {
- // targets="--with-target-hosts='host:debug'"
- // }
-
- // sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} ${targets} --quiet"
-
- // //Compile the project
- // sh 'make -j 8 --no-print-directory'
- // }
- // }
-
- debug = true
- release = Settings.RunAllTests || Settings.RunBenchmark
- build_stage('Build : configure', true) {
- // Build outside of the src tree to ease cleaning
- dir (BuildDir) {
- //Configure the conpilation (Output is not relevant)
- //Use the current directory as the installation target so nothing escapes the sandbox
- //Also specify the compiler by hand
- targets=""
- if( Settings.RunAllTests || Settings.RunBenchmark ) {
- targets="--with-target-hosts='host:debug,host:nodebug'"
- } else {
- targets="--with-target-hosts='host:debug'"
- }
-
- sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} ${targets} --quiet"
-
- // Configure libcfa
- sh 'make -j 8 --no-print-directory configure-libcfa'
- }
- }
-
- build_stage('Build : cfa-cpp', true) {
- // Build outside of the src tree to ease cleaning
- dir (BuildDir) {
- // Build driver
- sh 'make -j 8 --no-print-directory -C driver'
-
- // Build translator
- sh 'make -j 8 --no-print-directory -C src'
- }
- }
-
- build_stage('Build : libcfa(debug)', debug) {
- // Build outside of the src tree to ease cleaning
- dir (BuildDir) {
- sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-debug"
- }
- }
-
- build_stage('Build : libcfa(nodebug)', release) {
- // Build outside of the src tree to ease cleaning
- dir (BuildDir) {
- sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-nodebug"
- }
- }
-}
-
-def test() {
- build_stage('Test: short', !Settings.RunAllTests) {
- dir (BuildDir) {
- //Run the tests from the tests directory
- sh 'make --no-print-directory -C tests'
- }
- }
-
- build_stage('Test: full', Settings.RunAllTests) {
- dir (BuildDir) {
- //Run the tests from the tests directory
- sh 'make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes'
- sh 'make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no '
- }
- }
-}
-
-def benchmark() {
- build_stage('Benchmark', Settings.RunBenchmark) {
- dir (BuildDir) {
- //Append bench results
- sh "make --no-print-directory -C benchmark jenkins"
- }
- }
-}
-
-def build_doc() {
- build_stage('Documentation', Settings.BuildDocumentation) {
- dir ('doc/user') {
- make_doc()
- }
-
- dir ('doc/refrat') {
- make_doc()
- }
- }
-}
-
-def publish() {
- build_stage('Publish', true) {
-
- if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
-
- def groupCompile = new PlotGroup('Compilation', 'seconds', true)
- def groupConcurrency = new PlotGroup('Concurrency', 'nanoseconds', false)
-
- //Then publish the results
- do_plot(Settings.RunBenchmark && Settings.Publish, 'compile' , groupCompile , 'Compilation')
- do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch', groupConcurrency, 'Context Switching')
- do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex' , groupConcurrency, 'Mutual Exclusion')
- do_plot(Settings.RunBenchmark && Settings.Publish, 'signal' , groupConcurrency, 'Internal and External Scheduling')
- }
-}
-
-//===========================================================================================================
-//Routine responsible of sending the email notification once the build is completed
-//===========================================================================================================
-def GitLogMessage() {
- if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
-
- sh "${SrcDir}/tools/PrettyGitLogs.sh ${SrcDir} ${BuildDir} ${Settings.GitOldRef} ${Settings.GitNewRef}"
-
- def gitUpdate = readFile("${BuildDir}/GIT_UPDATE")
- def gitLog = readFile("${BuildDir}/GIT_LOG")
- def gitDiff = readFile("${BuildDir}/GIT_DIFF")
-
- return """
-
-The branch ${env.BRANCH_NAME} has been updated.
-${gitUpdate}
-
-
-Check console output at ${env.BUILD_URL} to view the results.
-
-- Status --------------------------------------------------------------
-
-BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}
-
-- Log -----------------------------------------------------------------
-
-
-${gitLog}
-
-
------------------------------------------------------------------------
-
-Summary of changes:
-${gitDiff}
-
-"""
-}
-
-//Standard build email notification
-def email(boolean log) {
- //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
- //Configurations for email format
- echo 'Notifying users of result'
-
- def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
- def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
- def email_body = """This is an automated email from the Jenkins build machine. It was
-generated because of a git hooks/post-receive script following
-a ref change which was pushed to the C\u2200 repository.
-""" + GitLogMessage()
-
- def email_to = !Settings.IsSandbox ? "cforall@lists.uwaterloo.ca" : "tdelisle@uwaterloo.ca"
-
- if( Settings && !Settings.Silent ) {
- //send email notification
- emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
- } else {
- echo "Would send email to: ${email_to}"
- echo "With title: ${email_subject}"
- echo "Content: \n${email_body}"
- }
-}
-
-//===========================================================================================================
-// Helper classes/variables/routines
-//===========================================================================================================
-//Description of a compiler (Must be serializable since pipelines are persistent)
-class CC_Desc implements Serializable {
- public String name
- public String CXX
- public String CC
-
- CC_Desc(String name, String CXX, String CC) {
- this.name = name
- this.CXX = CXX
- this.CC = CC
- }
-}
-
-//Description of an architecture (Must be serializable since pipelines are persistent)
-class Arch_Desc implements Serializable {
- public String name
- public String flags
- public String node
-
- Arch_Desc(String name, String flags, String node) {
- this.name = name
- this.flags = flags
- this.node = node
- }
-}
-
-class BuildSettings implements Serializable {
- public final CC_Desc Compiler
- public final Arch_Desc Architecture
- public final Boolean RunAllTests
- public final Boolean RunBenchmark
- public final Boolean BuildDocumentation
- public final Boolean Publish
- public final Boolean Silent
- public final Boolean IsSandbox
- public final String DescLong
- public final String DescShort
-
- public String GitNewRef
- public String GitOldRef
-
- BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
- switch( param.Compiler ) {
- case 'gcc-6':
- this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
- break
- case 'gcc-5':
- this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
- break
- case 'gcc-4.9':
- this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
- break
- case 'clang':
- this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
- break
- default :
- error "Unhandled compiler : ${cc}"
- }
-
- switch( param.Architecture ) {
- case 'x64':
- this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
- break
- case 'x86':
- this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
- break
- default :
- error "Unhandled architecture : ${arch}"
- }
-
- this.IsSandbox = (branch == "jenkins-sandbox")
- this.RunAllTests = param.RunAllTests
- this.RunBenchmark = param.RunBenchmark
- this.BuildDocumentation = param.BuildDocumentation
- this.Publish = param.Publish
- this.Silent = param.Silent
-
- def full = param.RunAllTests ? " (Full)" : ""
- this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
-
- this.DescLong = """Compiler : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
-Architecture : ${ this.Architecture.name }
-Arc Flags : ${ this.Architecture.flags }
-Run All Tests : ${ this.RunAllTests.toString() }
-Run Benchmark : ${ this.RunBenchmark.toString() }
-Build Documentation : ${ this.BuildDocumentation.toString() }
-Publish : ${ this.Publish.toString() }
-Silent : ${ this.Silent.toString() }
-"""
-
- this.GitNewRef = ''
- this.GitOldRef = ''
- }
-}
-
-class PlotGroup implements Serializable {
- public String name
- public String unit
- public boolean log
-
- PlotGroup(String name, String unit, boolean log) {
- this.name = name
- this.unit = unit
- this.log = log
- }
-}
-
-def prepare_build() {
- // prepare the properties
- properties ([ \
- [$class: 'ParametersDefinitionProperty', \
- parameterDefinitions: [ \
- [$class: 'ChoiceParameterDefinition', \
- description: 'Which compiler to use', \
- name: 'Compiler', \
- choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang', \
- defaultValue: 'gcc-6', \
- ], \
- [$class: 'ChoiceParameterDefinition', \
- description: 'The target architecture', \
- name: 'Architecture', \
- choices: 'x64\nx86', \
- defaultValue: 'x64', \
- ], \
- [$class: 'BooleanParameterDefinition', \
- description: 'If false, only the quick test suite is ran', \
- name: 'RunAllTests', \
- defaultValue: false, \
- ], \
- [$class: 'BooleanParameterDefinition', \
- description: 'If true, jenkins also runs benchmarks', \
- name: 'RunBenchmark', \
- defaultValue: false, \
- ], \
- [$class: 'BooleanParameterDefinition', \
- description: 'If true, jenkins also builds documentation', \
- name: 'BuildDocumentation', \
- defaultValue: true, \
- ], \
- [$class: 'BooleanParameterDefinition', \
- description: 'If true, jenkins also publishes results', \
- name: 'Publish', \
- defaultValue: false, \
- ], \
- [$class: 'BooleanParameterDefinition', \
- description: 'If true, jenkins will not send emails', \
- name: 'Silent', \
- defaultValue: false, \
- ], \
- ],
- ]])
-
- // It's unfortunate but it looks like we need to checkout the entire repo just to get the pretty git printer
- checkout scm
-
- final settings = new BuildSettings(params, env.BRANCH_NAME)
-
- currentBuild.description = settings.DescShort
- echo settings.DescLong
-
- return settings
-}
-
-def build_stage(String name, boolean run, Closure block ) {
- StageName = name
- echo " -------- ${StageName} -------- "
- if(run) {
- stage(name, block)
- } else {
- stage(name) { Utils.markStageSkippedForConditional(STAGE_NAME) }
- }
-}
-
-def make_doc() {
- def err = null
- try {
- sh 'make clean > /dev/null'
- sh 'make > /dev/null 2>&1'
- }
- catch (Exception caughtError) {
- err = caughtError //rethrow error later
- sh 'cat build/*.log'
- }
- finally {
- if (err) throw err // Must re-throw exception to propagate error
- }
-}
-
-def do_plot(boolean new_data, String file, PlotGroup group, String title) {
-
- if(new_data) {
- echo "Publishing new data"
- }
-
- def series = new_data ? [[
- file: "${file}.csv",
- exclusionValues: '',
- displayTableFlag: false,
- inclusionFlag: 'OFF',
- url: ''
- ]] : [];
-
- echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
- dir("${BuildDir}/benchmark/") {
- plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
- csvSeries: series,
- group: "${group.name}",
- title: "${title}",
- style: 'lineSimple',
- exclZero: false,
- keepRecords: false,
- logarithmic: group.log,
- numBuilds: '120',
- useDescr: true,
- yaxis: group.unit,
- yaxisMaximum: '',
- yaxisMinimum: ''
- }
-}
Index: Jenkinsfile_disabled
===================================================================
--- Jenkinsfile_disabled (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
+++ Jenkinsfile_disabled (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -0,0 +1,514 @@
+#!groovy
+
+import groovy.transform.Field
+
+// For skipping stages
+import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
+
+//===========================================================================================================
+// Main loop of the compilation
+//===========================================================================================================
+
+node('master') {
+ // Globals
+ BuildDir = pwd tmp: true
+ SrcDir = pwd tmp: false
+ Settings = null
+ StageName = ''
+
+ // Local variables
+ def err = null
+ def log_needed = false
+
+ currentBuild.result = "SUCCESS"
+
+ try {
+ //Wrap build to add timestamp to command line
+ wrap([$class: 'TimestamperBuildWrapper']) {
+
+ Settings = prepare_build()
+
+ node(Settings.Architecture.node) {
+ BuildDir = pwd tmp: true
+ SrcDir = pwd tmp: false
+
+ clean()
+
+ checkout()
+
+ build()
+
+ test()
+
+ benchmark()
+
+ build_doc()
+
+ publish()
+ }
+
+ // Update the build directories when exiting the node
+ BuildDir = pwd tmp: true
+ SrcDir = pwd tmp: false
+ }
+ }
+
+ //If an exception is caught we need to change the status and remember to
+ //attach the build log to the email
+ catch (Exception caughtError) {
+ //rethrow error later
+ err = caughtError
+
+ echo err.toString()
+
+ //An error has occured, the build log is relevent
+ log_needed = true
+
+ //Store the result of the build log
+ currentBuild.result = "${StageName} FAILURE".trim()
+ }
+
+ finally {
+ //Send email with final results if this is not a full build
+ email(log_needed)
+
+ echo 'Build Completed'
+
+ /* Must re-throw exception to propagate error */
+ if (err) {
+ throw err
+ }
+ }
+}
+//===========================================================================================================
+// Main compilation routines
+//===========================================================================================================
+def clean() {
+ build_stage('Cleanup', true) {
+ // clean the build by wipping the build directory
+ dir(BuildDir) {
+ deleteDir()
+ }
+ }
+}
+
+//Compilation script is done here but environnement set-up and error handling is done in main loop
+def checkout() {
+ build_stage('Checkout', true) {
+ //checkout the source code and clean the repo
+ final scmVars = checkout scm
+ Settings.GitNewRef = scmVars.GIT_COMMIT
+ Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT
+
+ echo GitLogMessage()
+ }
+}
+
+def build() {
+ // build_stage('Build', true) {
+ // // Build outside of the src tree to ease cleaning
+ // dir (BuildDir) {
+ // //Configure the conpilation (Output is not relevant)
+ // //Use the current directory as the installation target so nothing escapes the sandbox
+ // //Also specify the compiler by hand
+ // targets=""
+ // if( Settings.RunAllTests || Settings.RunBenchmark ) {
+ // targets="--with-target-hosts='host:debug,host:nodebug'"
+ // } else {
+ // targets="--with-target-hosts='host:debug'"
+ // }
+
+ // sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} ${targets} --quiet"
+
+ // //Compile the project
+ // sh 'make -j 8 --no-print-directory'
+ // }
+ // }
+
+ debug = true
+ release = Settings.RunAllTests || Settings.RunBenchmark
+ build_stage('Build : configure', true) {
+ // Build outside of the src tree to ease cleaning
+ dir (BuildDir) {
+ //Configure the conpilation (Output is not relevant)
+ //Use the current directory as the installation target so nothing escapes the sandbox
+ //Also specify the compiler by hand
+ targets=""
+ if( Settings.RunAllTests || Settings.RunBenchmark ) {
+ targets="--with-target-hosts='host:debug,host:nodebug'"
+ } else {
+ targets="--with-target-hosts='host:debug'"
+ }
+
+ sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} ${targets} --quiet"
+
+ // Configure libcfa
+ sh 'make -j 8 --no-print-directory configure-libcfa'
+ }
+ }
+
+ build_stage('Build : cfa-cpp', true) {
+ // Build outside of the src tree to ease cleaning
+ dir (BuildDir) {
+ // Build driver
+ sh 'make -j 8 --no-print-directory -C driver'
+
+ // Build translator
+ sh 'make -j 8 --no-print-directory -C src'
+ }
+ }
+
+ build_stage('Build : libcfa(debug)', debug) {
+ // Build outside of the src tree to ease cleaning
+ dir (BuildDir) {
+ sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-debug"
+ }
+ }
+
+ build_stage('Build : libcfa(nodebug)', release) {
+ // Build outside of the src tree to ease cleaning
+ dir (BuildDir) {
+ sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-nodebug"
+ }
+ }
+}
+
+def test() {
+ build_stage('Test: short', !Settings.RunAllTests) {
+ dir (BuildDir) {
+ //Run the tests from the tests directory
+ sh 'make --no-print-directory -C tests'
+ }
+ }
+
+ build_stage('Test: full', Settings.RunAllTests) {
+ dir (BuildDir) {
+ //Run the tests from the tests directory
+ sh 'make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes'
+ sh 'make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no '
+ }
+ }
+}
+
+def benchmark() {
+ build_stage('Benchmark', Settings.RunBenchmark) {
+ dir (BuildDir) {
+ //Append bench results
+ sh "make --no-print-directory -C benchmark jenkins"
+ }
+ }
+}
+
+def build_doc() {
+ build_stage('Documentation', Settings.BuildDocumentation) {
+ dir ('doc/user') {
+ make_doc()
+ }
+
+ dir ('doc/refrat') {
+ make_doc()
+ }
+ }
+}
+
+def publish() {
+ build_stage('Publish', true) {
+
+ if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
+
+ def groupCompile = new PlotGroup('Compilation', 'seconds', true)
+ def groupConcurrency = new PlotGroup('Concurrency', 'nanoseconds', false)
+
+ //Then publish the results
+ do_plot(Settings.RunBenchmark && Settings.Publish, 'compile' , groupCompile , 'Compilation')
+ do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch', groupConcurrency, 'Context Switching')
+ do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex' , groupConcurrency, 'Mutual Exclusion')
+ do_plot(Settings.RunBenchmark && Settings.Publish, 'signal' , groupConcurrency, 'Internal and External Scheduling')
+ }
+}
+
+//===========================================================================================================
+//Routine responsible of sending the email notification once the build is completed
+//===========================================================================================================
+def GitLogMessage() {
+ if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
+
+ sh "${SrcDir}/tools/PrettyGitLogs.sh ${SrcDir} ${BuildDir} ${Settings.GitOldRef} ${Settings.GitNewRef}"
+
+ def gitUpdate = readFile("${BuildDir}/GIT_UPDATE")
+ def gitLog = readFile("${BuildDir}/GIT_LOG")
+ def gitDiff = readFile("${BuildDir}/GIT_DIFF")
+
+ return """
+
+The branch ${env.BRANCH_NAME} has been updated.
+${gitUpdate}
+
+
+Check console output at ${env.BUILD_URL} to view the results.
+
+- Status --------------------------------------------------------------
+
+BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}
+
+- Log -----------------------------------------------------------------
+
+
+${gitLog}
+
+
+-----------------------------------------------------------------------
+
+Summary of changes:
+${gitDiff}
+
+"""
+}
+
+//Standard build email notification
+def email(boolean log) {
+ //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
+ //Configurations for email format
+ echo 'Notifying users of result'
+
+ def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
+ def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
+ def email_body = """This is an automated email from the Jenkins build machine. It was
+generated because of a git hooks/post-receive script following
+a ref change which was pushed to the C\u2200 repository.
+""" + GitLogMessage()
+
+ def email_to = !Settings.IsSandbox ? "cforall@lists.uwaterloo.ca" : "tdelisle@uwaterloo.ca"
+
+ if( Settings && !Settings.Silent ) {
+ //send email notification
+ emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
+ } else {
+ echo "Would send email to: ${email_to}"
+ echo "With title: ${email_subject}"
+ echo "Content: \n${email_body}"
+ }
+}
+
+//===========================================================================================================
+// Helper classes/variables/routines
+//===========================================================================================================
+//Description of a compiler (Must be serializable since pipelines are persistent)
+class CC_Desc implements Serializable {
+ public String name
+ public String CXX
+ public String CC
+
+ CC_Desc(String name, String CXX, String CC) {
+ this.name = name
+ this.CXX = CXX
+ this.CC = CC
+ }
+}
+
+//Description of an architecture (Must be serializable since pipelines are persistent)
+class Arch_Desc implements Serializable {
+ public String name
+ public String flags
+ public String node
+
+ Arch_Desc(String name, String flags, String node) {
+ this.name = name
+ this.flags = flags
+ this.node = node
+ }
+}
+
+class BuildSettings implements Serializable {
+ public final CC_Desc Compiler
+ public final Arch_Desc Architecture
+ public final Boolean RunAllTests
+ public final Boolean RunBenchmark
+ public final Boolean BuildDocumentation
+ public final Boolean Publish
+ public final Boolean Silent
+ public final Boolean IsSandbox
+ public final String DescLong
+ public final String DescShort
+
+ public String GitNewRef
+ public String GitOldRef
+
+ BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
+ switch( param.Compiler ) {
+ case 'gcc-6':
+ this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
+ break
+ case 'gcc-5':
+ this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
+ break
+ case 'gcc-4.9':
+ this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
+ break
+ case 'clang':
+ this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
+ break
+ default :
+ error "Unhandled compiler : ${cc}"
+ }
+
+ switch( param.Architecture ) {
+ case 'x64':
+ this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
+ break
+ case 'x86':
+ this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
+ break
+ default :
+ error "Unhandled architecture : ${arch}"
+ }
+
+ this.IsSandbox = (branch == "jenkins-sandbox")
+ this.RunAllTests = param.RunAllTests
+ this.RunBenchmark = param.RunBenchmark
+ this.BuildDocumentation = param.BuildDocumentation
+ this.Publish = param.Publish
+ this.Silent = param.Silent
+
+ def full = param.RunAllTests ? " (Full)" : ""
+ this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
+
+ this.DescLong = """Compiler : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
+Architecture : ${ this.Architecture.name }
+Arc Flags : ${ this.Architecture.flags }
+Run All Tests : ${ this.RunAllTests.toString() }
+Run Benchmark : ${ this.RunBenchmark.toString() }
+Build Documentation : ${ this.BuildDocumentation.toString() }
+Publish : ${ this.Publish.toString() }
+Silent : ${ this.Silent.toString() }
+"""
+
+ this.GitNewRef = ''
+ this.GitOldRef = ''
+ }
+}
+
+class PlotGroup implements Serializable {
+ public String name
+ public String unit
+ public boolean log
+
+ PlotGroup(String name, String unit, boolean log) {
+ this.name = name
+ this.unit = unit
+ this.log = log
+ }
+}
+
+def prepare_build() {
+ // prepare the properties
+ properties ([ \
+ [$class: 'ParametersDefinitionProperty', \
+ parameterDefinitions: [ \
+ [$class: 'ChoiceParameterDefinition', \
+ description: 'Which compiler to use', \
+ name: 'Compiler', \
+ choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang', \
+ defaultValue: 'gcc-6', \
+ ], \
+ [$class: 'ChoiceParameterDefinition', \
+ description: 'The target architecture', \
+ name: 'Architecture', \
+ choices: 'x64\nx86', \
+ defaultValue: 'x64', \
+ ], \
+ [$class: 'BooleanParameterDefinition', \
+ description: 'If false, only the quick test suite is ran', \
+ name: 'RunAllTests', \
+ defaultValue: false, \
+ ], \
+ [$class: 'BooleanParameterDefinition', \
+ description: 'If true, jenkins also runs benchmarks', \
+ name: 'RunBenchmark', \
+ defaultValue: false, \
+ ], \
+ [$class: 'BooleanParameterDefinition', \
+ description: 'If true, jenkins also builds documentation', \
+ name: 'BuildDocumentation', \
+ defaultValue: true, \
+ ], \
+ [$class: 'BooleanParameterDefinition', \
+ description: 'If true, jenkins also publishes results', \
+ name: 'Publish', \
+ defaultValue: false, \
+ ], \
+ [$class: 'BooleanParameterDefinition', \
+ description: 'If true, jenkins will not send emails', \
+ name: 'Silent', \
+ defaultValue: false, \
+ ], \
+ ],
+ ]])
+
+ // It's unfortunate but it looks like we need to checkout the entire repo just to get the pretty git printer
+ checkout scm
+
+ final settings = new BuildSettings(params, env.BRANCH_NAME)
+
+ currentBuild.description = settings.DescShort
+ echo settings.DescLong
+
+ return settings
+}
+
+def build_stage(String name, boolean run, Closure block ) {
+ StageName = name
+ echo " -------- ${StageName} -------- "
+ if(run) {
+ stage(name, block)
+ } else {
+ stage(name) { Utils.markStageSkippedForConditional(STAGE_NAME) }
+ }
+}
+
+def make_doc() {
+ def err = null
+ try {
+ sh 'make clean > /dev/null'
+ sh 'make > /dev/null 2>&1'
+ }
+ catch (Exception caughtError) {
+ err = caughtError //rethrow error later
+ sh 'cat build/*.log'
+ }
+ finally {
+ if (err) throw err // Must re-throw exception to propagate error
+ }
+}
+
+def do_plot(boolean new_data, String file, PlotGroup group, String title) {
+
+ if(new_data) {
+ echo "Publishing new data"
+ }
+
+ def series = new_data ? [[
+ file: "${file}.csv",
+ exclusionValues: '',
+ displayTableFlag: false,
+ inclusionFlag: 'OFF',
+ url: ''
+ ]] : [];
+
+ echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
+ dir("${BuildDir}/benchmark/") {
+ plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
+ csvSeries: series,
+ group: "${group.name}",
+ title: "${title}",
+ style: 'lineSimple',
+ exclZero: false,
+ keepRecords: false,
+ logarithmic: group.log,
+ numBuilds: '120',
+ useDescr: true,
+ yaxis: group.unit,
+ yaxisMaximum: '',
+ yaxisMinimum: ''
+ }
+}
Index: src/AST/Attribute.hpp
===================================================================
--- src/AST/Attribute.hpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Attribute.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -51,4 +51,6 @@
template
friend node_t * mutate(const node_t * node);
+ template
+ friend node_t * shallowCopy(const node_t * node);
};
Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Convert.cpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -608,4 +608,15 @@
tgt->result = get().accept1(src->result);
+ // Unconditionally use a clone of the result type.
+ // We know this will leak some objects: much of the immediate conversion result.
+ // In some cases, using the conversion result directly gives unintended object sharing.
+ // A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache.
+ // But tgt->result must be fully owned privately by tgt.
+ // Applying these conservative copies here means
+ // - weak references point at the declaration's copy, not these expr.result copies (good)
+ // - we copy more objects than really needed (bad, tolerated)
+ if (tgt->result) {
+ tgt->result = tgt->result->clone();
+ }
return visitBaseExpr_skipResultType(src, tgt);
}
Index: src/AST/Copy.hpp
===================================================================
--- src/AST/Copy.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
+++ src/AST/Copy.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -0,0 +1,126 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Copy.hpp -- Provides functions to copy the AST.
+//
+// Author : Andrew Beach
+// Created On : Wed Jul 10 16:13:00 2019
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr Jul 11 10:38:00 2019
+// Update Count : 0
+//
+
+#include "Decl.hpp"
+#include "Expr.hpp"
+#include "Pass.hpp"
+#include "Stmt.hpp"
+#include "Type.hpp"
+
+namespace ast {
+
+template
+node_t * shallowCopy( const node_t * node );
+/* Create a shallow copy of the node given.
+ *
+ * The new node has all the same primitive field values and points to the
+ * same children nodes as the parent.
+ */
+
+template
+node_t * deepCopy( const node_t * localRoot );
+/* Create a deep copy of the tree rooted at localRoot.
+ *
+ * This creates a copy of every node in the sub-tree (reachable by strong
+ * reference from local_root) and updates any readonly pointers on those nodes
+ * that point to another node in the sub-tree to the new version of that node.
+ */
+
+class DeepCopyCore {
+ std::unordered_map< const Node *, const Node * > nodeCache;
+ std::unordered_set< readonly * > readonlyCache;
+
+public:
+ template
+ const node_t * previsit( const node_t * node ) {
+ const node_t * copy = shallowCopy( node );
+ nodeCache.insert( std::make_pair( node, copy ) );
+ return copy;
+ }
+
+ void postvisit( const AggregateDecl * node ) {
+ readonlyCache.insert( (readonly *) & node->parent );
+ }
+
+ void postvisit( const StructInstType * node ) {
+ readonlyCache.insert( (readonly *) & node->base );
+ }
+
+ void postvisit( const UnionInstType * node ) {
+ readonlyCache.insert( (readonly *) & node->base );
+ }
+
+ void postvisit( const EnumInstType * node ) {
+ readonlyCache.insert( (readonly *) & node->base );
+ }
+
+ void postvisit( const TraitInstType * node ) {
+ readonlyCache.insert( (readonly *) & node->base );
+ }
+
+ void postvisit( const TypeInstType * node ) {
+ readonlyCache.insert( (readonly *) & node->base );
+ }
+
+ void postvisit( const ImplicitCtorDtorStmt * node ) {
+ readonlyCache.insert( (readonly *) & node->callStmt );
+ }
+
+ void postvisit( const MemberExpr * node ) {
+ readonlyCache.insert( (readonly *) & node->member );
+ }
+
+ void postvisit( const VariableExpr * node ) {
+ readonlyCache.insert( (readonly *) & node->var );
+ }
+
+ void postvisit( const OffsetofExpr * node ) {
+ readonlyCache.insert( (readonly *) & node->member );
+ }
+
+ void postvisit( const DeletedExpr * node ) {
+ readonlyCache.insert( (readonly *) & node->deleteStmt );
+ }
+
+ void readonlyUpdates() {
+ for ( readonly * ptr : readonlyCache ) {
+ auto it = nodeCache.find( ptr->get() );
+ if ( nodeCache.end() != it ) {
+ *ptr = it->second;
+ }
+ }
+ }
+};
+
+template
+node_t * shallowCopy( const node_t * localRoot ) {
+ return localRoot->clone();
+}
+
+template
+node_t * deepCopy( const node_t * localRoot ) {
+ Pass< DeepCopyCore > dc;
+ node_t const * newRoot = localRoot->accept( dc );
+ dc.pass.readonlyUpdates();
+ return const_cast< node_t * >( newRoot );
+}
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/Decl.cpp
===================================================================
--- src/AST/Decl.cpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Decl.cpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -52,5 +52,7 @@
const Type * FunctionDecl::get_type() const { return type.get(); }
-void FunctionDecl::set_type(Type * t) { type = strict_dynamic_cast< FunctionType* >( t ); }
+void FunctionDecl::set_type( const Type * t ) {
+ type = strict_dynamic_cast< const FunctionType * >( t );
+}
// --- TypeDecl
Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Decl.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -32,5 +32,7 @@
// Must be included in *all* AST classes; should be #undef'd at the end of the file
-#define MUTATE_FRIEND template friend node_t * mutate(const node_t * node);
+#define MUTATE_FRIEND \
+ template friend node_t * mutate(const node_t * node); \
+ template friend node_t * shallowCopy(const node_t * node);
namespace ast {
@@ -87,5 +89,5 @@
virtual const Type * get_type() const = 0;
/// Set type of this declaration. May be verified by subclass
- virtual void set_type(Type *) = 0;
+ virtual void set_type( const Type * ) = 0;
const DeclWithType * accept( Visitor & v ) const override = 0;
@@ -110,5 +112,5 @@
const Type* get_type() const override { return type; }
- void set_type( Type * ty ) override { type = ty; }
+ void set_type( const Type * ty ) override { type = ty; }
const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
@@ -132,5 +134,5 @@
const Type * get_type() const override;
- void set_type(Type * t) override;
+ void set_type( const Type * t ) override;
bool has_body() const { return stmts; }
@@ -149,6 +151,7 @@
std::vector> assertions;
- NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
- Type* b, Linkage::Spec spec = Linkage::Cforall )
+ NamedTypeDecl(
+ const CodeLocation & loc, const std::string & name, Storage::Classes storage,
+ const Type * b, Linkage::Spec spec = Linkage::Cforall )
: Decl( loc, name, storage, spec ), base( b ), params(), assertions() {}
@@ -185,6 +188,7 @@
};
- TypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, Type* b,
- TypeVar::Kind k, bool s, Type* i = nullptr )
+ TypeDecl(
+ const CodeLocation & loc, const std::string & name, Storage::Classes storage,
+ const Type * b, TypeVar::Kind k, bool s, const Type * i = nullptr )
: NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeVar::Ttype || s ),
init( i ) {}
Index: src/AST/Eval.hpp
===================================================================
--- src/AST/Eval.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
+++ src/AST/Eval.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -0,0 +1,37 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Eval.hpp --
+//
+// Author : Aaron B. Moss
+// Created On : Fri Jun 28 14:00:00 2019
+// Last Modified By : Aaron B. Moss
+// Created On : Fri Jun 28 14:00:00 2019
+// Update Count : 1
+//
+
+#include
+#include
+
+#include "Expr.hpp"
+
+namespace ast {
+
+/// Create a new UntypedExpr with the given arguments
+template< typename... Args >
+UntypedExpr * call( const CodeLocation & loc, const std::string & name, Args &&... args ) {
+ return new UntypedExpr {
+ loc, new NameExpr { loc, name },
+ std::vector< ptr< Expr > > { std::forward< Args >( args )... } };
+}
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Expr.cpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -20,4 +20,5 @@
#include
+#include "Eval.hpp" // for call
#include "GenericSubstitution.hpp"
#include "Stmt.hpp"
@@ -51,7 +52,5 @@
assert( arg );
- UntypedExpr * ret = new UntypedExpr{
- loc, new NameExpr{loc, "*?"}, std::vector>{ ptr{ arg } }
- };
+ UntypedExpr * ret = call( loc, "*?", arg );
if ( const Type * ty = arg->result ) {
const Type * base = InitTweak::getPointerBase( ty );
@@ -74,7 +73,5 @@
assert( lhs && rhs );
- UntypedExpr * ret = new UntypedExpr{
- loc, new NameExpr{loc, "?=?"}, std::vector>{ ptr{ lhs }, ptr{ rhs } }
- };
+ UntypedExpr * ret = call( loc, "?=?", lhs, rhs );
if ( lhs->result && rhs->result ) {
// if both expressions are typed, assumes that this assignment is a C bitwise assignment,
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Expr.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -30,5 +30,8 @@
// Must be included in *all* AST classes; should be #undef'd at the end of the file
-#define MUTATE_FRIEND template friend node_t * mutate(const node_t * node);
+#define MUTATE_FRIEND \
+ template friend node_t * mutate(const node_t * node); \
+ template friend node_t * shallowCopy(const node_t * node);
+
class ConverterOldToNew;
Index: src/AST/ForallSubstitutionTable.cpp
===================================================================
--- src/AST/ForallSubstitutionTable.cpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
+++ src/AST/ForallSubstitutionTable.cpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -0,0 +1,54 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// ForallSubstitutionTable.cpp --
+//
+// Author : Aaron B. Moss
+// Created On : Thu Jun 27 14:00:00 2019
+// Last Modified By : Aaron B. Moss
+// Last Modified On : Thu Jun 27 14:00:00 2019
+// Update Count : 1
+//
+
+#include "ForallSubstitutionTable.hpp"
+
+#include
+#include
+
+#include "Decl.hpp"
+#include "Node.hpp"
+#include "Type.hpp"
+#include "Visitor.hpp"
+
+namespace ast {
+
+std::vector< ptr< TypeDecl > > ForallSubstitutionTable::clone(
+ const std::vector< ptr< TypeDecl > > & forall, Visitor & v
+) {
+ std::vector< ptr< TypeDecl > > new_forall;
+ new_forall.reserve( forall.size() );
+
+ for ( const ast::TypeDecl * d : forall ) {
+ // create cloned type decl and insert into substitution map before further mutation
+ auto new_d = new ast::TypeDecl{
+ d->location, d->name, d->storage, d->base, d->kind, d->sized, d->init };
+ decls.insert( d, new_d );
+ // perform other mutations and add to output
+ auto newer_d = v.visit( new_d );
+ assert( new_d == newer_d && "Newly cloned TypeDecl must retain identity" );
+ new_forall.emplace_back( new_d );
+ }
+
+ return new_forall;
+}
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/ForallSubstitutionTable.hpp
===================================================================
--- src/AST/ForallSubstitutionTable.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
+++ src/AST/ForallSubstitutionTable.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -0,0 +1,57 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// ForallSubstitutionTable.hpp --
+//
+// Author : Aaron B. Moss
+// Created On : Thu Jun 27 14:00:00 2019
+// Last Modified By : Aaron B. Moss
+// Last Modified On : Thu Jun 27 14:00:00 2019
+// Update Count : 1
+//
+
+#pragma once
+
+#include
+
+#include "Node.hpp" // for ptr
+#include "Common/ScopedMap.h"
+
+namespace ast {
+
+class TypeDecl;
+class Visitor;
+
+/// Wrapper for TypeDecl substitution table
+class ForallSubstitutionTable {
+ ScopedMap< const TypeDecl *, const TypeDecl * > decls;
+
+public:
+ /// Replaces given declaration with value in the table, if present, otherwise returns argument
+ const TypeDecl * replace( const TypeDecl * d ) {
+ auto it = decls.find( d );
+ if ( it != decls.end() ) return it->second;
+ return d;
+ }
+
+ /// Builds a new forall list mutated according to the given visitor
+ std::vector< ptr< TypeDecl > > clone(
+ const std::vector< ptr< TypeDecl > > & forall, Visitor & v );
+
+ /// Introduces a new lexical scope
+ void beginScope() { decls.beginScope(); }
+
+ /// Concludes a lexical scope
+ void endScope() { decls.endScope(); }
+};
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/ForallSubstitutor.hpp
===================================================================
--- src/AST/ForallSubstitutor.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
+++ src/AST/ForallSubstitutor.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -0,0 +1,58 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// ForallSubstitutor.hpp --
+//
+// Author : Aaron B. Moss
+// Created On : Wed Jun 26 15:00:00 2019
+// Last Modified By : Aaron B. Moss
+// Last Modified On : Wed Jun 26 15:00:00 2019
+// Update Count : 1
+//
+
+#include "Pass.hpp"
+
+namespace ast {
+
+class Expr;
+
+/// Visitor that correctly substitutes TypeDecl while maintaining TypeInstType bindings.
+/// Also has some convenience methods to mutate fields.
+struct ForallSubstitutor : public WithForallSubstitutor, public WithVisitorRef {
+ /// Substitute TypeInstType base type
+ readonly< TypeDecl > operator() ( const readonly< TypeDecl > & o ) {
+ return subs.replace( o );
+ }
+
+ /// Make new forall-list clone
+ ParameterizedType::ForallList operator() ( const ParameterizedType::ForallList & o ) {
+ return subs.clone( o, *visitor );
+ }
+
+ /// Substitute parameter/return type
+ std::vector< ptr< DeclWithType > > operator() ( const std::vector< ptr< DeclWithType > > & o ) {
+ std::vector< ptr< DeclWithType > > n;
+ n.reserve( o.size() );
+ for ( const DeclWithType * d : o ) { n.emplace_back( d->accept( *visitor ) ); }
+ return n;
+ }
+
+ /// Substitute type parameter list
+ std::vector< ptr< Expr > > operator() ( const std::vector< ptr< Expr > > & o ) {
+ std::vector< ptr< Expr > > n;
+ n.reserve( o.size() );
+ for ( const Expr * d : o ) { n.emplace_back( d->accept( *visitor ) ); }
+ return n;
+ }
+};
+
+} // namespace ast
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/Init.hpp
===================================================================
--- src/AST/Init.hpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Init.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -25,5 +25,7 @@
// Must be included in *all* AST classes; should be #undef'd at the end of the file
-#define MUTATE_FRIEND template friend node_t * mutate(const node_t * node);
+#define MUTATE_FRIEND \
+ template friend node_t * mutate(const node_t * node); \
+ template friend node_t * shallowCopy(const node_t * node);
namespace ast {
Index: src/AST/Node.cpp
===================================================================
--- src/AST/Node.cpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Node.cpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -17,4 +17,5 @@
#include "Fwd.hpp"
+#include // MEMORY DEBUG -- for raise
#include
@@ -29,12 +30,33 @@
#include "Print.hpp"
-template< typename node_t, enum ast::Node::ref_type ref_t >
-void ast::ptr_base::_inc( const node_t * node ) { node->increment(ref_t); }
-
-template< typename node_t, enum ast::Node::ref_type ref_t >
-void ast::ptr_base::_dec( const node_t * node ) { node->decrement(ref_t); }
-
-template< typename node_t, enum ast::Node::ref_type ref_t >
-void ast::ptr_base::_check() const { if(node) assert(node->was_ever_strong == false || node->strong_count > 0); }
+/// MEMORY DEBUG -- allows breaking on ref-count changes of dynamically chosen object.
+/// Process to use in GDB:
+/// break ast::Node::_trap()
+/// run
+/// set variable MEM_TRAP_OBJ =
+/// disable
+/// continue
+void * MEM_TRAP_OBJ = nullptr;
+
+void _trap( const void * node ) {
+ if ( node == MEM_TRAP_OBJ ) std::raise(SIGTRAP);
+}
+
+template< typename node_t, enum ast::Node::ref_type ref_t >
+void ast::ptr_base::_inc( const node_t * node ) {
+ node->increment(ref_t);
+ _trap( node );
+}
+
+template< typename node_t, enum ast::Node::ref_type ref_t >
+void ast::ptr_base::_dec( const node_t * node, bool do_delete ) {
+ _trap( node );
+ node->decrement(ref_t, do_delete );
+}
+
+template< typename node_t, enum ast::Node::ref_type ref_t >
+void ast::ptr_base::_check() const {
+ // if(node) assert(node->was_ever_strong == false || node->strong_count > 0);
+}
template< typename node_t, enum ast::Node::ref_type ref_t >
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Node.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -38,5 +38,5 @@
Node& operator= (const Node&) = delete;
Node& operator= (Node&&) = delete;
- virtual ~Node() = default;
+ virtual ~Node() {}
virtual const Node * accept( Visitor & v ) const = 0;
@@ -57,4 +57,6 @@
template
friend node_t * mutate(const node_t * node);
+ template
+ friend node_t * shallowCopy(const node_t * node);
mutable size_t strong_count = 0;
@@ -69,5 +71,5 @@
}
- void decrement(ast::Node::ref_type ref) const {
+ void decrement(ast::Node::ref_type ref, bool do_delete = true) const {
switch (ref) {
case ref_type::strong: strong_count--; break;
@@ -75,5 +77,5 @@
}
- if(!strong_count && !weak_count) {
+ if( do_delete && !strong_count && !weak_count) {
delete this;
}
@@ -123,4 +125,13 @@
(ret->*field)[i] = std::forward< field_t >( val );
return ret;
+}
+
+/// Mutate an entire indexed collection by cloning to accepted value
+template
+const node_t * mutate_each( const node_t * node, coll_t parent_t::* field, Visitor & v ) {
+ for ( unsigned i = 0; i < (node->*field).size(); ++i ) {
+ node = mutate_field_index( node, field, i, (node->*field)[i]->accept( v ) );
+ }
+ return node;
}
@@ -219,4 +230,13 @@
operator const node_t * () const { _check(); return node; }
+ const node_t * release() {
+ const node_t * ret = node;
+ if ( node ) {
+ _dec(node, false);
+ node = nullptr;
+ }
+ return ret;
+ }
+
/// wrapper for convenient access to dynamic_cast
template
@@ -244,5 +264,5 @@
void _inc( const node_t * other );
- void _dec( const node_t * other );
+ void _dec( const node_t * other, bool do_delete = true );
void _check() const;
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Pass.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -35,4 +35,6 @@
#include "AST/SymbolTable.hpp"
+#include "AST/ForallSubstitutionTable.hpp"
+
// Private prelude header, needed for some of the magic tricks this class pulls off
#include "AST/Pass.proto.hpp"
@@ -46,20 +48,21 @@
//
// Several additional features are available through inheritance
-// | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the
-// current expression
-// | WithStmtsToAdd - provides the ability to insert statements before or after the current
-// statement by adding new statements into stmtsToAddBefore or
-// stmtsToAddAfter respectively.
-// | WithDeclsToAdd - provides the ability to insert declarations before or after the current
-// declarations by adding new DeclStmt into declsToAddBefore or
-// declsToAddAfter respectively.
-// | WithShortCircuiting - provides the ability to skip visiting child nodes; set visit_children
-// to false in pre{visit,visit} to skip visiting children
-// | WithGuards - provides the ability to save/restore data like a LIFO stack; to save,
-// call GuardValue with the variable to save, the variable will
-// automatically be restored to its previous value after the corresponding
-// postvisit/postmutate teminates.
-// | WithVisitorRef - provides an pointer to the templated visitor wrapper
-// | WithSymbolTable - provides symbol table functionality
+// | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the
+// current expression
+// | WithStmtsToAdd - provides the ability to insert statements before or after the current
+// statement by adding new statements into stmtsToAddBefore or
+// stmtsToAddAfter respectively.
+// | WithDeclsToAdd - provides the ability to insert declarations before or after the
+// current declarations by adding new DeclStmt into declsToAddBefore or
+// declsToAddAfter respectively.
+// | WithShortCircuiting - provides the ability to skip visiting child nodes; set visit_children
+// to false in pre{visit,visit} to skip visiting children
+// | WithGuards - provides the ability to save/restore data like a LIFO stack; to save,
+// call GuardValue with the variable to save, the variable will
+// automatically be restored to its previous value after the
+// corresponding postvisit/postmutate teminates.
+// | WithVisitorRef - provides an pointer to the templated visitor wrapper
+// | WithSymbolTable - provides symbol table functionality
+// | WithForallSubstitutor - maintains links between TypeInstType and TypeDecl under mutation
//-------------------------------------------------------------------------------------------------
template< typename pass_t >
@@ -201,4 +204,8 @@
container_t< ptr > call_accept( const container_t< ptr > & container );
+ /// Mutate forall-list, accounting for presence of type substitution map
+ template
+ void mutate_forall( const node_t *& );
+
public:
/// Logic to call the accept and mutate the parent if needed, delegates call to accept
@@ -209,6 +216,6 @@
/// Internal RAII guard for symbol table features
struct guard_symtab {
- guard_symtab( Pass & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); }
- ~guard_symtab() { __pass::symtab::leave(pass, 0); }
+ guard_symtab( Pass & pass ): pass( pass ) { __pass::symtab::enter(pass.pass, 0); }
+ ~guard_symtab() { __pass::symtab::leave(pass.pass, 0); }
Pass & pass;
};
@@ -216,7 +223,16 @@
/// Internal RAII guard for scope features
struct guard_scope {
- guard_scope( Pass & pass ): pass( pass ) { __pass::scope::enter(pass, 0); }
- ~guard_scope() { __pass::scope::leave(pass, 0); }
+ guard_scope( Pass & pass ): pass( pass ) { __pass::scope::enter(pass.pass, 0); }
+ ~guard_scope() { __pass::scope::leave(pass.pass, 0); }
Pass & pass;
+ };
+
+ /// Internal RAII guard for forall substitutions
+ struct guard_forall_subs {
+ guard_forall_subs( Pass & pass, const ParameterizedType * type )
+ : pass( pass ), type( type ) { __pass::forall::enter(pass.pass, 0, type ); }
+ ~guard_forall_subs() { __pass::forall::leave(pass.pass, 0, type ); }
+ Pass & pass;
+ const ParameterizedType * type;
};
@@ -313,4 +329,10 @@
SymbolTable symtab;
};
+
+/// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl
+struct WithForallSubstitutor {
+ ForallSubstitutionTable subs;
+};
+
}
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Pass.impl.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -127,8 +127,7 @@
, decltype( node->accept(*this) )
>::type
-
{
__pedantic_pass_assert( __visit_children() );
- __pedantic_pass_assert( expr );
+ __pedantic_pass_assert( node );
static_assert( !std::is_base_of::value, "ERROR");
@@ -323,4 +322,20 @@
}
+
+ template< typename pass_t >
+ template< typename node_t >
+ void ast::Pass< pass_t >::mutate_forall( const node_t *& node ) {
+ if ( auto subs = __pass::forall::subs( pass, 0 ) ) {
+ // tracking TypeDecl substitution, full clone
+ if ( node->forall.empty() ) return;
+
+ node_t * mut = mutate( node );
+ mut->forall = subs->clone( node->forall, *this );
+ node = mut;
+ } else {
+ // not tracking TypeDecl substitution, just mutate
+ maybe_accept( node, &node_t::forall );
+ }
+ }
}
@@ -429,12 +444,12 @@
guard_symtab guard { *this };
// implicit add __func__ identifier as specified in the C manual 6.4.2.2
- static ast::ObjectDecl func(
- node->location, "__func__",
- new ast::ArrayType(
- new ast::BasicType( ast::BasicType::Char, ast::CV::Qualifiers( ast::CV::Const ) ),
+ static ast::ptr< ast::ObjectDecl > func{ new ast::ObjectDecl{
+ CodeLocation{}, "__func__",
+ new ast::ArrayType{
+ new ast::BasicType{ ast::BasicType::Char, ast::CV::Const },
nullptr, VariableLen, DynamicDim
- )
- );
- __pass::symtab::addId( pass, 0, &func );
+ }
+ } };
+ __pass::symtab::addId( pass, 0, func );
VISIT(
maybe_accept( node, &FunctionDecl::type );
@@ -610,8 +625,8 @@
VISIT({
// do not enter a new scope if inFunction is true - needs to check old state before the assignment
- auto guard1 = makeFuncGuard( [this, inFunction = this->inFunction]() {
- if ( ! inFunction ) __pass::symtab::enter(pass, 0);
- }, [this, inFunction = this->inFunction]() {
- if ( ! inFunction ) __pass::symtab::leave(pass, 0);
+ auto guard1 = makeFuncGuard( [this, inFunctionCpy = this->inFunction]() {
+ if ( ! inFunctionCpy ) __pass::symtab::enter(pass, 0);
+ }, [this, inFunctionCpy = this->inFunction]() {
+ if ( ! inFunctionCpy ) __pass::symtab::leave(pass, 0);
});
ValueGuard< bool > guard2( inFunction );
@@ -1667,9 +1682,10 @@
VISIT_START( node );
- VISIT(
- maybe_accept( node, &FunctionType::forall );
+ VISIT({
+ guard_forall_subs forall_guard { *this, node };
+ mutate_forall( node );
maybe_accept( node, &FunctionType::returns );
maybe_accept( node, &FunctionType::params );
- )
+ })
VISIT_END( Type, node );
@@ -1686,5 +1702,6 @@
VISIT({
guard_symtab guard { *this };
- maybe_accept( node, &StructInstType::forall );
+ guard_forall_subs forall_guard { *this, node };
+ mutate_forall( node );
maybe_accept( node, &StructInstType::params );
})
@@ -1699,11 +1716,12 @@
VISIT_START( node );
- __pass::symtab::addStruct( pass, 0, node->name );
-
- {
+ __pass::symtab::addUnion( pass, 0, node->name );
+
+ VISIT({
guard_symtab guard { *this };
- maybe_accept( node, &UnionInstType::forall );
+ guard_forall_subs forall_guard { *this, node };
+ mutate_forall( node );
maybe_accept( node, &UnionInstType::params );
- }
+ })
VISIT_END( Type, node );
@@ -1716,8 +1734,9 @@
VISIT_START( node );
- VISIT(
- maybe_accept( node, &EnumInstType::forall );
+ VISIT({
+ guard_forall_subs forall_guard { *this, node };
+ mutate_forall( node );
maybe_accept( node, &EnumInstType::params );
- )
+ })
VISIT_END( Type, node );
@@ -1730,8 +1749,9 @@
VISIT_START( node );
- VISIT(
- maybe_accept( node, &TraitInstType::forall );
+ VISIT({
+ guard_forall_subs forall_guard { *this, node };
+ mutate_forall( node );
maybe_accept( node, &TraitInstType::params );
- )
+ })
VISIT_END( Type, node );
@@ -1745,6 +1765,11 @@
VISIT(
- maybe_accept( node, &TypeInstType::forall );
- maybe_accept( node, &TypeInstType::params );
+ {
+ guard_forall_subs forall_guard { *this, node };
+ mutate_forall( node );
+ maybe_accept( node, &TypeInstType::params );
+ }
+ // ensure that base re-bound if doing substitution
+ __pass::forall::replace( pass, 0, node );
)
@@ -1895,5 +1920,5 @@
guard_symtab guard { *this };
auto new_node = p.second->accept( *this );
- if (new_node != p.second) mutated = false;
+ if (new_node != p.second) mutated = true;
new_map.insert({ p.first, new_node });
}
@@ -1911,5 +1936,5 @@
guard_symtab guard { *this };
auto new_node = p.second->accept( *this );
- if (new_node != p.second) mutated = false;
+ if (new_node != p.second) mutated = true;
new_map.insert({ p.first, new_node });
}
Index: src/AST/Pass.proto.hpp
===================================================================
--- src/AST/Pass.proto.hpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Pass.proto.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -263,12 +263,12 @@
template
static inline void leave( pass_t &, long ) {}
- };
-
- // Finally certain pass desire an up to date symbol table automatically
+ } // namespace scope
+
+ // Certain passes desire an up to date symbol table automatically
// detect the presence of a member name `symtab` and call all the members appropriately
namespace symtab {
// Some simple scoping rules
template
- static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab.enterScope(), void() ) {
+ static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab, void() ) {
pass.symtab.enterScope();
}
@@ -278,5 +278,5 @@
template
- static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab.leaveScope(), void() ) {
+ static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab, void() ) {
pass.symtab.leaveScope();
}
@@ -356,5 +356,49 @@
#undef SYMTAB_FUNC1
#undef SYMTAB_FUNC2
- };
-};
-};
+ } // namespace symtab
+
+ // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType.
+ // Detect the presence of a member name `subs` and call all members appropriately
+ namespace forall {
+ // Some simple scoping rules
+ template
+ static inline auto enter( pass_t & pass, int, const ast::ParameterizedType * type )
+ -> decltype( pass.subs, void() ) {
+ if ( ! type->forall.empty() ) pass.subs.beginScope();
+ }
+
+ template
+ static inline auto enter( pass_t &, long, const ast::ParameterizedType * ) {}
+
+ template
+ static inline auto leave( pass_t & pass, int, const ast::ParameterizedType * type )
+ -> decltype( pass.subs, void() ) {
+ if ( ! type->forall.empty() ) { pass.subs.endScope(); }
+ }
+
+ template
+ static inline auto leave( pass_t &, long, const ast::ParameterizedType * ) {}
+
+ // Get the substitution table, if present
+ template
+ static inline auto subs( pass_t & pass, int ) -> decltype( &pass.subs ) {
+ return &pass.subs;
+ }
+
+ template
+ static inline ast::ForallSubstitutionTable * subs( pass_t &, long ) { return nullptr; }
+
+ // Replaces a TypeInstType's base TypeDecl according to the table
+ template
+ static inline auto replace( pass_t & pass, int, const ast::TypeInstType *& inst )
+ -> decltype( pass.subs, void() ) {
+ inst = ast::mutate_field(
+ inst, &ast::TypeInstType::base, pass.subs.replace( inst->base ) );
+ }
+
+ template
+ static inline auto replace( pass_t &, long, const ast::TypeInstType *& ) {}
+
+ } // namespace forall
+} // namespace __pass
+} // namespace ast
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Stmt.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -27,5 +27,7 @@
// Must be included in *all* AST classes; should be #undef'd at the end of the file
-#define MUTATE_FRIEND template friend node_t * mutate(const node_t * node);
+#define MUTATE_FRIEND \
+ template friend node_t * mutate(const node_t * node); \
+ template friend node_t * shallowCopy(const node_t * node);
namespace ast {
Index: src/AST/Type.cpp
===================================================================
--- src/AST/Type.cpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Type.cpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -21,5 +21,7 @@
#include "Decl.hpp"
+#include "ForallSubstitutor.hpp" // for substituteForall
#include "Init.hpp"
+#include "Common/utility.h" // for copy, move
#include "InitTweak/InitTweak.h" // for getPointerBase
#include "Tuples/Tuples.h" // for isTtype
@@ -91,5 +93,22 @@
);
+// --- ParameterizedType
+
+void ParameterizedType::initWithSub(
+ const ParameterizedType & o, Pass< ForallSubstitutor > & sub
+) {
+ forall = sub.pass( o.forall );
+}
+
// --- FunctionType
+
+FunctionType::FunctionType( const FunctionType & o )
+: ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),
+ isVarArgs( o.isVarArgs ) {
+ Pass< ForallSubstitutor > sub;
+ initWithSub( o, sub ); // initialize substitution map
+ returns = sub.pass( o.returns ); // apply to return and parameter types
+ params = sub.pass( o.params );
+}
namespace {
@@ -107,4 +126,17 @@
// --- ReferenceToType
+
+void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {
+ ParameterizedType::initWithSub( o, sub ); // initialize substitution
+ params = sub.pass( o.params ); // apply to parameters
+}
+
+ReferenceToType::ReferenceToType( const ReferenceToType & o )
+: ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ),
+ hoistType( o.hoistType ) {
+ Pass< ForallSubstitutor > sub;
+ initWithSub( o, sub );
+}
+
std::vector> ReferenceToType::lookup( const std::string& name ) const {
assertf( aggr(), "Must have aggregate to perform lookup" );
@@ -119,7 +151,7 @@
// --- StructInstType
-StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q,
- std::vector>&& as )
-: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
+StructInstType::StructInstType(
+ const StructDecl * b, CV::Qualifiers q, std::vector>&& as )
+: ReferenceToType( b->name, q, move(as) ), base( b ) {}
bool StructInstType::isComplete() const { return base ? base->body : false; }
@@ -127,7 +159,7 @@
// --- UnionInstType
-UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q,
- std::vector>&& as )
-: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
+UnionInstType::UnionInstType(
+ const UnionDecl * b, CV::Qualifiers q, std::vector>&& as )
+: ReferenceToType( b->name, q, move(as) ), base( b ) {}
bool UnionInstType::isComplete() const { return base ? base->body : false; }
@@ -135,7 +167,7 @@
// --- EnumInstType
-EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q,
- std::vector>&& as )
-: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
+EnumInstType::EnumInstType(
+ const EnumDecl * b, CV::Qualifiers q, std::vector>&& as )
+: ReferenceToType( b->name, q, move(as) ), base( b ) {}
bool EnumInstType::isComplete() const { return base ? base->body : false; }
@@ -143,9 +175,16 @@
// --- TraitInstType
-TraitInstType::TraitInstType( const TraitDecl * b, CV::Qualifiers q,
- std::vector>&& as )
-: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
+TraitInstType::TraitInstType(
+ const TraitDecl * b, CV::Qualifiers q, std::vector>&& as )
+: ReferenceToType( b->name, q, move(as) ), base( b ) {}
// --- TypeInstType
+
+TypeInstType::TypeInstType( const TypeInstType & o )
+: ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
+ Pass< ForallSubstitutor > sub;
+ initWithSub( o, sub ); // initialize substitution
+ base = sub.pass( o.base ); // apply to base type
+}
void TypeInstType::set_base( const TypeDecl * b ) {
@@ -159,5 +198,5 @@
TupleType::TupleType( std::vector> && ts, CV::Qualifiers q )
-: Type( q ), types( std::move(ts) ), members() {
+: Type( q ), types( move(ts) ), members() {
// This constructor is awkward. `TupleType` needs to contain objects so that members can be
// named, but members without initializer nodes end up getting constructors, which breaks
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/Type.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -30,7 +30,13 @@
// Must be included in *all* AST classes; should be #undef'd at the end of the file
-#define MUTATE_FRIEND template friend node_t * mutate(const node_t * node);
+#define MUTATE_FRIEND \
+ template friend node_t * mutate(const node_t * node); \
+ template friend node_t * shallowCopy(const node_t * node);
namespace ast {
+
+template< typename T > class Pass;
+
+struct ForallSubstitutor;
class Type : public Node {
@@ -164,5 +170,5 @@
static const char *typeNames[];
- BasicType( Kind k, CV::Qualifiers q = {}, std::vector> && as = {} )
+ BasicType( Kind k, CV::Qualifiers q = {}, std::vector> && as = {} )
: Type(q, std::move(as)), kind(k) {}
@@ -266,4 +272,7 @@
/// Base type for potentially forall-qualified types
class ParameterizedType : public Type {
+protected:
+ /// initializes forall with substitutor
+ void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub );
public:
using ForallList = std::vector>;
@@ -277,4 +286,11 @@
ParameterizedType( CV::Qualifiers q, std::vector> && as = {} )
: Type(q, std::move(as)), forall() {}
+
+ // enforce use of ForallSubstitutor to copy parameterized type
+ ParameterizedType( const ParameterizedType & ) = delete;
+
+ ParameterizedType( ParameterizedType && ) = default;
+
+ // no need to change destructor, and operator= deleted in Node
private:
@@ -302,4 +318,6 @@
: ParameterizedType(q), returns(), params(), isVarArgs(va) {}
+ FunctionType( const FunctionType & o );
+
/// true if either the parameters or return values contain a tttype
bool isTtype() const;
@@ -315,4 +333,7 @@
/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
class ReferenceToType : public ParameterizedType {
+protected:
+ /// Initializes forall and parameters based on substitutor
+ void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );
public:
std::vector> params;
@@ -320,7 +341,9 @@
bool hoistType = false;
- ReferenceToType( const std::string& n, CV::Qualifiers q = {},
- std::vector> && as = {} )
+ ReferenceToType(
+ const std::string& n, CV::Qualifiers q = {}, std::vector> && as = {} )
: ParameterizedType(q, std::move(as)), params(), name(n) {}
+
+ ReferenceToType( const ReferenceToType & o );
/// Gets aggregate declaration this type refers to
@@ -339,9 +362,10 @@
readonly base;
- StructInstType( const std::string& n, CV::Qualifiers q = {},
- std::vector> && as = {} )
+ StructInstType(
+ const std::string& n, CV::Qualifiers q = {}, std::vector> && as = {} )
: ReferenceToType( n, q, std::move(as) ), base() {}
- StructInstType( const StructDecl * b, CV::Qualifiers q = {},
- std::vector> && as = {} );
+
+ StructInstType(
+ const StructDecl * b, CV::Qualifiers q = {}, std::vector> && as = {} );
bool isComplete() const override;
@@ -360,9 +384,10 @@
readonly base;
- UnionInstType( const std::string& n, CV::Qualifiers q = {},
- std::vector> && as = {} )
+ UnionInstType(
+ const std::string& n, CV::Qualifiers q = {}, std::vector> && as = {} )
: ReferenceToType( n, q, std::move(as) ), base() {}
- UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
- std::vector> && as = {} );
+
+ UnionInstType(
+ const UnionDecl * b, CV::Qualifiers q = {}, std::vector> && as = {} );
bool isComplete() const override;
@@ -381,9 +406,10 @@
readonly base;
- EnumInstType( const std::string& n, CV::Qualifiers q = {},
- std::vector> && as = {} )
+ EnumInstType(
+ const std::string& n, CV::Qualifiers q = {}, std::vector> && as = {} )
: ReferenceToType( n, q, std::move(as) ), base() {}
- EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
- std::vector> && as = {} );
+
+ EnumInstType(
+ const EnumDecl * b, CV::Qualifiers q = {}, std::vector> && as = {} );
bool isComplete() const override;
@@ -402,9 +428,10 @@
readonly base;
- TraitInstType( const std::string& n, CV::Qualifiers q = {},
- std::vector> && as = {} )
+ TraitInstType(
+ const std::string& n, CV::Qualifiers q = {}, std::vector> && as = {} )
: ReferenceToType( n, q, std::move(as) ), base() {}
- TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
- std::vector> && as = {} );
+
+ TraitInstType(
+ const TraitDecl * b, CV::Qualifiers q = {}, std::vector> && as = {} );
// not meaningful for TraitInstType
@@ -425,10 +452,15 @@
TypeVar::Kind kind;
- TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
+ TypeInstType(
+ const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
std::vector> && as = {} )
: ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
- TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
+
+ TypeInstType(
+ const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
std::vector> && as = {} )
: ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
+
+ TypeInstType( const TypeInstType & o );
/// sets `base`, updating `kind` correctly
Index: src/AST/TypeSubstitution.cpp
===================================================================
--- src/AST/TypeSubstitution.cpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/TypeSubstitution.cpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -92,5 +92,5 @@
namespace {
struct EnvTrimmer {
- ptr env;
+ const TypeSubstitution * env;
TypeSubstitution * newEnv;
EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
@@ -108,11 +108,6 @@
if ( env ) {
TypeSubstitution * newEnv = new TypeSubstitution();
-#if TIME_TO_CONVERT_PASSES
Pass trimmer( env, newEnv );
expr->accept( trimmer );
-#else
- (void)expr;
- (void)env;
-#endif
return newEnv;
}
@@ -121,19 +116,15 @@
void TypeSubstitution::normalize() {
-#if TIME_TO_CONVERT_PASSES
- PassVisitor sub( *this, true );
+ Pass sub( *this, true );
do {
sub.pass.subCount = 0;
sub.pass.freeOnly = true;
for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
- i->second = i->second->acceptMutator( sub );
+ i->second = i->second->accept( sub );
}
} while ( sub.pass.subCount );
-#endif
-}
-
-#if TIME_TO_CONVERT_PASSES
-
-Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) {
+}
+
+const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) {
BoundVarsType::const_iterator bound = boundVars.find( inst->name );
if ( bound != boundVars.end() ) return inst;
@@ -146,5 +137,5 @@
// Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here.
// TODO: investigate preventing type variables from being bound to themselves in the first place.
- if ( TypeInstType * replacement = i->second.as() ) {
+ if ( const TypeInstType * replacement = i->second.as() ) {
if ( inst->name == replacement->name ) {
return inst;
@@ -153,13 +144,14 @@
// std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl;
subCount++;
- Type * newtype = i->second->clone();
- newtype->get_qualifiers() |= inst->get_qualifiers();
- delete inst;
- // Note: need to recursively apply substitution to the new type because normalize does not substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
- return newtype->acceptMutator( *visitor );
- } // if
-}
-
-Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) {
+ ptr newType = i->second; // force clone if needed
+ add_qualifiers( newType, inst->qualifiers );
+ // Note: need to recursively apply substitution to the new type because normalize does not
+ // substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
+ newType = newType->accept( *visitor );
+ return newType.release();
+ } // if
+}
+
+const Expr * TypeSubstitution::Substituter::postvisit( const NameExpr * nameExpr ) {
VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
if ( i == sub.varEnv.end() ) {
@@ -168,45 +160,43 @@
subCount++;
delete nameExpr;
- return i->second->clone();
- } // if
-}
-
-void TypeSubstitution::Substituter::premutate( Type * type ) {
+ return i->second;
+ } // if
+}
+
+void TypeSubstitution::Substituter::previsit( const ParameterizedType * ptype ) {
GuardValue( boundVars );
// bind type variables from forall-qualifiers
if ( freeOnly ) {
- for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
- boundVars.insert( (*tyvar)->name );
+ for ( const TypeDecl * tyvar : ptype->forall ) {
+ boundVars.insert( tyvar->name );
} // for
} // if
}
-template< typename TypeClass >
-void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) {
+void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) {
GuardValue( boundVars );
// bind type variables from forall-qualifiers
if ( freeOnly ) {
- for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
- boundVars.insert( (*tyvar)->name );
+ for ( const TypeDecl * tyvar : type->forall ) {
+ boundVars.insert( tyvar->name );
} // for
// bind type variables from generic type instantiations
- std::list< TypeDecl* > *baseParameters = type->get_baseParameters();
- if ( baseParameters && ! type->parameters.empty() ) {
- for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) {
- boundVars.insert( (*tyvar)->name );
- } // for
- } // if
- } // if
-}
-
-void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) {
+ if ( auto decl = type->aggr() ) {
+ if ( ! type->params.empty() ) {
+ for ( const TypeDecl * tyvar : decl->params ) {
+ boundVars.insert( tyvar->name );
+ } // for
+ } // if
+ }
+ } // if
+}
+
+void TypeSubstitution::Substituter::previsit( const StructInstType * aggregateUseType ) {
handleAggregateType( aggregateUseType );
}
-void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) {
+void TypeSubstitution::Substituter::previsit( const UnionInstType *aggregateUseType ) {
handleAggregateType( aggregateUseType );
}
-
-#endif
} // namespace ast
Index: src/AST/TypeSubstitution.hpp
===================================================================
--- src/AST/TypeSubstitution.hpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/TypeSubstitution.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -155,18 +155,14 @@
Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
-#if TIME_TO_CONVERT_PASSES
-
- Type * postmutate( TypeInstType * aggregateUseType );
- Expression * postmutate( NameExpr * nameExpr );
+ const Type * postvisit( const TypeInstType * aggregateUseType );
+ const Expr * postvisit( const NameExpr * nameExpr );
/// Records type variable bindings from forall-statements
- void premutate( Type * type );
+ void previsit( const ParameterizedType * type );
/// Records type variable bindings from forall-statements and instantiations of generic types
- template< typename TypeClass > void handleAggregateType( TypeClass * type );
-
- void premutate( StructInstType * aggregateUseType );
- void premutate( UnionInstType * aggregateUseType );
-
-#endif
+ void handleAggregateType( const ReferenceToType * type );
+
+ void previsit( const StructInstType * aggregateUseType );
+ void previsit( const UnionInstType * aggregateUseType );
const TypeSubstitution & sub;
Index: src/AST/module.mk
===================================================================
--- src/AST/module.mk (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/AST/module.mk (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -22,4 +22,5 @@
AST/DeclReplacer.cpp \
AST/Expr.cpp \
+ AST/ForallSubstitutionTable.cpp \
AST/GenericSubstitution.cpp \
AST/Init.cpp \
Index: src/Common/ScopedMap.h
===================================================================
--- src/Common/ScopedMap.h (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/Common/ScopedMap.h (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -249,4 +249,6 @@
/// Gets the note at the given scope
+ Note& getNote() { return scopes.back().note; }
+ const Note& getNote() const { return scopes.back().note; }
Note& getNote( size_type i ) { return scopes[i].note; }
const Note& getNote( size_type i ) const { return scopes[i].note; }
Index: src/Makefile.in
===================================================================
--- src/Makefile.in (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/Makefile.in (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -168,4 +168,5 @@
AST/Convert.$(OBJEXT) AST/Decl.$(OBJEXT) \
AST/DeclReplacer.$(OBJEXT) AST/Expr.$(OBJEXT) \
+ AST/ForallSubstitutionTable.$(OBJEXT) \
AST/GenericSubstitution.$(OBJEXT) AST/Init.$(OBJEXT) \
AST/LinkageSpec.$(OBJEXT) AST/Node.$(OBJEXT) \
@@ -585,4 +586,5 @@
AST/DeclReplacer.cpp \
AST/Expr.cpp \
+ AST/ForallSubstitutionTable.cpp \
AST/GenericSubstitution.cpp \
AST/Init.cpp \
@@ -759,4 +761,6 @@
AST/$(DEPDIR)/$(am__dirstamp)
AST/Expr.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
+AST/ForallSubstitutionTable.$(OBJEXT): AST/$(am__dirstamp) \
+ AST/$(DEPDIR)/$(am__dirstamp)
AST/GenericSubstitution.$(OBJEXT): AST/$(am__dirstamp) \
AST/$(DEPDIR)/$(am__dirstamp)
@@ -1212,4 +1216,5 @@
@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/DeclReplacer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Expr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/ForallSubstitutionTable.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/GenericSubstitution.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Init.Po@am__quote@
Index: src/ResolvExpr/AdjustExprType.cc
===================================================================
--- src/ResolvExpr/AdjustExprType.cc (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/ResolvExpr/AdjustExprType.cc (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -100,35 +100,36 @@
namespace {
- struct AdjustExprType_new final : public ast::WithShortCircuiting {
+ class AdjustExprType_new final : public ast::WithShortCircuiting {
+ const ast::SymbolTable & symtab;
+ public:
const ast::TypeEnvironment & tenv;
- const ast::SymbolTable & symtab;
AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
- : tenv( e ), symtab( syms ) {}
+ : symtab( syms ), tenv( e ) {}
- void premutate( const ast::VoidType * ) { visit_children = false; }
- void premutate( const ast::BasicType * ) { visit_children = false; }
- void premutate( const ast::PointerType * ) { visit_children = false; }
- void premutate( const ast::ArrayType * ) { visit_children = false; }
- void premutate( const ast::FunctionType * ) { visit_children = false; }
- void premutate( const ast::StructInstType * ) { visit_children = false; }
- void premutate( const ast::UnionInstType * ) { visit_children = false; }
- void premutate( const ast::EnumInstType * ) { visit_children = false; }
- void premutate( const ast::TraitInstType * ) { visit_children = false; }
- void premutate( const ast::TypeInstType * ) { visit_children = false; }
- void premutate( const ast::TupleType * ) { visit_children = false; }
- void premutate( const ast::VarArgsType * ) { visit_children = false; }
- void premutate( const ast::ZeroType * ) { visit_children = false; }
- void premutate( const ast::OneType * ) { visit_children = false; }
+ void previsit( const ast::VoidType * ) { visit_children = false; }
+ void previsit( const ast::BasicType * ) { visit_children = false; }
+ void previsit( const ast::PointerType * ) { visit_children = false; }
+ void previsit( const ast::ArrayType * ) { visit_children = false; }
+ void previsit( const ast::FunctionType * ) { visit_children = false; }
+ void previsit( const ast::StructInstType * ) { visit_children = false; }
+ void previsit( const ast::UnionInstType * ) { visit_children = false; }
+ void previsit( const ast::EnumInstType * ) { visit_children = false; }
+ void previsit( const ast::TraitInstType * ) { visit_children = false; }
+ void previsit( const ast::TypeInstType * ) { visit_children = false; }
+ void previsit( const ast::TupleType * ) { visit_children = false; }
+ void previsit( const ast::VarArgsType * ) { visit_children = false; }
+ void previsit( const ast::ZeroType * ) { visit_children = false; }
+ void previsit( const ast::OneType * ) { visit_children = false; }
- const ast::Type * postmutate( const ast::ArrayType * at ) {
+ const ast::Type * postvisit( const ast::ArrayType * at ) {
return new ast::PointerType{ at->base, at->qualifiers };
}
- const ast::Type * postmutate( const ast::FunctionType * ft ) {
+ const ast::Type * postvisit( const ast::FunctionType * ft ) {
return new ast::PointerType{ ft };
}
- const ast::Type * postmutate( const ast::TypeInstType * inst ) {
+ const ast::Type * postvisit( const ast::TypeInstType * inst ) {
// replace known function-type-variables with pointer-to-function
if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) {
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/ResolvExpr/CandidateFinder.cpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -370,7 +370,5 @@
// push empty tuple expression
newResult.parent = i;
- std::vector< ast::ptr< ast::Expr > > emptyList;
- newResult.expr =
- new ast::TupleExpr{ CodeLocation{}, move( emptyList ) };
+ newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };
argType = newResult.expr->result;
} else {
@@ -548,5 +546,5 @@
genStart = genEnd;
- return genEnd != results.size();
+ return genEnd != results.size(); // were any new results added?
}
@@ -594,7 +592,8 @@
/// Actually visits expressions to find their candidate interpretations
- struct Finder final : public ast::WithShortCircuiting {
+ class Finder final : public ast::WithShortCircuiting {
+ const ast::SymbolTable & symtab;
+ public:
CandidateFinder & selfFinder;
- const ast::SymbolTable & symtab;
CandidateList & candidates;
const ast::TypeEnvironment & tenv;
@@ -602,5 +601,5 @@
Finder( CandidateFinder & f )
- : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
+ : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
targetType( f.targetType ) {}
@@ -676,6 +675,6 @@
ast::TypeEnvironment funcEnv{ func->env };
makeUnifiableVars( funcType, funcOpen, funcNeed );
- // add all type variables as open variables now so that those not used in the parameter
- // list are still considered open
+ // add all type variables as open variables now so that those not used in the
+ // parameter list are still considered open
funcEnv.add( funcType->forall );
@@ -1558,5 +1557,5 @@
std::vector< std::string > errors;
for ( CandidateRef & candidate : candidates ) {
- satisfyAssertions( candidate, symtab, satisfied, errors );
+ satisfyAssertions( candidate, localSyms, satisfied, errors );
}
@@ -1613,5 +1612,5 @@
r->expr = ast::mutate_field(
r->expr.get(), &ast::Expr::result,
- adjustExprType( r->expr->result, r->env, symtab ) );
+ adjustExprType( r->expr->result, r->env, localSyms ) );
}
}
@@ -1631,5 +1630,5 @@
for ( const auto & x : xs ) {
- out.emplace_back( symtab, env );
+ out.emplace_back( localSyms, env );
out.back().find( x, ResolvMode::withAdjustment() );
Index: src/ResolvExpr/CandidateFinder.hpp
===================================================================
--- src/ResolvExpr/CandidateFinder.hpp (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/ResolvExpr/CandidateFinder.hpp (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -28,12 +28,12 @@
struct CandidateFinder {
CandidateList candidates; ///< List of candidate resolutions
- const ast::SymbolTable & symtab; ///< Symbol table to lookup candidates
+ const ast::SymbolTable & localSyms; ///< Symbol table to lookup candidates
const ast::TypeEnvironment & env; ///< Substitutions performed in this resolution
ast::ptr< ast::Type > targetType; ///< Target type for resolution
CandidateFinder(
- const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
+ const ast::SymbolTable & syms, const ast::TypeEnvironment & env,
const ast::Type * tt = nullptr )
- : candidates(), symtab( symtab ), env( env ), targetType( tt ) {}
+ : candidates(), localSyms( syms ), env( env ), targetType( tt ) {}
/// Fill candidates with feasible resolutions for `expr`
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/ResolvExpr/CommonType.cc (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -939,5 +939,5 @@
ast::ptr< ast::Type > result;
const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >();
- const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >();
+ const ast::ReferenceType * ref2 = type2.as< ast::ReferenceType >();
if ( depth1 > depth2 ) {
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/ResolvExpr/ConversionCost.cc (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -10,6 +10,6 @@
// Created On : Sun May 17 07:06:19 2015
// Last Modified By : Andrew Beach
-// Last Modified On : Mon Jun 24 13:33:00 2019
-// Update Count : 26
+// Last Modified On : Thr Jul 4 10:56:00 2019
+// Update Count : 27
//
@@ -764,4 +764,8 @@
cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
}
+ } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
+ cost = Cost::zero;
+ // +1 for zero_t ->, +1 for disambiguation
+ cost.incSafe( maxIntCost + 2 );
}
}
@@ -781,7 +785,4 @@
cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
}
- } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
- cost = Cost::zero;
- cost.incSafe( maxIntCost + 2 );
}
}
Index: src/ResolvExpr/PolyCost.cc
===================================================================
--- src/ResolvExpr/PolyCost.cc (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/ResolvExpr/PolyCost.cc (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -58,11 +58,12 @@
// TODO: When the old PolyCost is torn out get rid of the _new suffix.
-struct PolyCost_new {
+class PolyCost_new {
+ const ast::SymbolTable &symtab;
+public:
int result;
- const ast::SymbolTable &symtab;
const ast::TypeEnvironment &env_;
- PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) :
- result( 0 ), symtab( symtab ), env_( env ) {}
+ PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env )
+ : symtab( symtab ), result( 0 ), env_( env ) {}
void previsit( const ast::TypeInstType * type ) {
Index: src/ResolvExpr/RenameVars.cc
===================================================================
--- src/ResolvExpr/RenameVars.cc (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/ResolvExpr/RenameVars.cc (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -19,4 +19,5 @@
#include // for pair
+#include "AST/ForallSubstitutionTable.hpp"
#include "AST/Pass.hpp"
#include "AST/Type.hpp"
@@ -30,4 +31,6 @@
#include "SynTree/Visitor.h" // for acceptAll, maybeAccept
+#include "AST/Copy.hpp"
+
namespace ResolvExpr {
@@ -37,6 +40,7 @@
int resetCount = 0;
ScopedMap< std::string, std::string > nameMap;
+ public:
+ ast::ForallSubstitutionTable subs;
- public:
void reset() {
level = 0;
@@ -44,8 +48,6 @@
}
- using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator;
-
void rename( TypeInstType * type ) {
- mapConstIterator it = nameMap.find( type->name );
+ auto it = nameMap.find( type->name );
if ( it != nameMap.end() ) {
type->name = it->second;
@@ -65,7 +67,6 @@
// ditto for assertion names, the next level in
level++;
- // acceptAll( td->assertions, *this );
- } // for
- } // if
+ }
+ }
}
@@ -77,10 +78,16 @@
const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
- mapConstIterator it = nameMap.find( type->name );
+ // re-linking of base type handled by WithForallSubstitutor
+
+ // rename
+ auto it = nameMap.find( type->name );
if ( it != nameMap.end() ) {
- ast::TypeInstType * mutType = ast::mutate( type );
- mutType->name = it->second;
- type = mutType;
+ // unconditionally mutate because map will *always* have different name,
+ // if this mutates, will *always* have been mutated by ForallSubstitutor above
+ ast::TypeInstType * mut = ast::mutate( type );
+ mut->name = it->second;
+ type = mut;
}
+
return type;
}
@@ -88,29 +95,32 @@
template
const NodeT * openLevel( const NodeT * type ) {
- if ( !type->forall.empty() ) {
- nameMap.beginScope();
- // Load new names from this forall clause and perform renaming.
- NodeT * mutType = ast::mutate( type );
- for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
- std::ostringstream output;
- output << "_" << resetCount << "_" << level << "_" << td->name;
- std::string newname( output.str() );
- nameMap[ td->name ] = newname;
- ++level;
+ if ( type->forall.empty() ) return type;
+
+ nameMap.beginScope();
- ast::TypeDecl * decl = ast::mutate( td.get() );
- decl->name = newname;
- td = decl;
- }
+ // Load new names from this forall clause and perform renaming.
+ NodeT * mutType = ast::mutate( type );
+ assert( type == mutType && "mutated type must be unique from ForallSubstitutor" );
+ for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
+ std::ostringstream output;
+ output << "_" << resetCount << "_" << level << "_" << td->name;
+ std::string newname = output.str();
+ nameMap[ td->name ] = newname;
+ ++level;
+
+ ast::TypeDecl * mutDecl = ast::mutate( td.get() );
+ assert( td == mutDecl && "mutated decl must be unique from ForallSubstitutor" );
+ mutDecl->name = newname;
+ // assertion above means `td = mutDecl;` is unnecessary
}
+ // assertion above means `type = mutType;` is unnecessary
+
return type;
}
- template
- const NodeT * closeLevel( const NodeT * type ) {
- if ( !type->forall.empty() ) {
- nameMap.endScope();
- }
- return type;
+ void closeLevel( const ast::ParameterizedType * type ) {
+ if ( type->forall.empty() ) return;
+
+ nameMap.endScope();
}
};
@@ -119,5 +129,5 @@
RenamingData renaming;
- struct RenameVars {
+ struct RenameVars_old {
void previsit( TypeInstType * instType ) {
renaming.openLevel( (Type*)instType );
@@ -130,4 +140,9 @@
renaming.closeLevel( type );
}
+ };
+
+ struct RenameVars_new /*: public ast::WithForallSubstitutor*/ {
+ #warning when old RenameVars goes away, replace hack below with global pass inheriting from WithForallSubstitutor
+ ast::ForallSubstitutionTable & subs = renaming.subs;
const ast::FunctionType * previsit( const ast::FunctionType * type ) {
@@ -146,6 +161,6 @@
return renaming.rename( renaming.openLevel( type ) );
}
- const ast::ParameterizedType * postvisit( const ast::ParameterizedType * type ) {
- return renaming.closeLevel( type );
+ void postvisit( const ast::ParameterizedType * type ) {
+ renaming.closeLevel( type );
}
};
@@ -154,11 +169,13 @@
void renameTyVars( Type * t ) {
- PassVisitor renamer;
+ PassVisitor renamer;
t->accept( renamer );
}
const ast::Type * renameTyVars( const ast::Type * t ) {
- ast::Pass renamer;
- return t->accept( renamer );
+ ast::Type *tc = ast::deepCopy(t);
+ ast::Pass renamer;
+// return t->accept( renamer );
+ return tc->accept( renamer );
}
Index: src/ResolvExpr/ResolveTypeof.cc
===================================================================
--- src/ResolvExpr/ResolveTypeof.cc (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/ResolvExpr/ResolveTypeof.cc (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -153,5 +153,5 @@
}
- return newType;
+ return newType.release();
}
};
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/ResolvExpr/Resolver.cc (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -1108,5 +1108,5 @@
// set up and resolve expression cast to void
- ast::CastExpr * untyped = new ast::CastExpr{ expr };
+ ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
CandidateRef choice = findUnfinishedKindExpression(
untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
@@ -1247,5 +1247,5 @@
};
- void resolve( std::list< ast::ptr >& translationUnit ) {
+ void resolve( std::list< ast::ptr< ast::Decl > >& translationUnit ) {
ast::Pass< Resolver_new > resolver;
accept_all( translationUnit, resolver );
@@ -1281,5 +1281,5 @@
ast::ptr< ast::FunctionDecl > ret = functionDecl;
for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
- const ast::ptr & d = functionDecl->type->params[i];
+ const ast::ptr< ast::DeclWithType > & d = functionDecl->type->params[i];
if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
@@ -1298,5 +1298,5 @@
}
}
- return ret.get();
+ return ret.release();
}
Index: src/ResolvExpr/SpecCost.cc
===================================================================
--- src/ResolvExpr/SpecCost.cc (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/ResolvExpr/SpecCost.cc (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -10,8 +10,9 @@
// Created On : Tue Oct 02 15:50:00 2018
// Last Modified By : Andrew Beach
-// Last Modified On : Wed Jun 19 10:43:00 2019
-// Update Count : 2
-//
-
+// Last Modified On : Wed Jul 3 11:07:00 2019
+// Update Count : 3
+//
+
+#include
#include
#include
@@ -129,4 +130,12 @@
typename std::add_pointer::type;
+ #warning Should use a standard maybe_accept
+ void maybe_accept( ast::Type const * type ) {
+ if ( type ) {
+ auto node = type->accept( *visitor );
+ assert( node == nullptr || node == type );
+ }
+ }
+
// Update the minimum to the new lowest non-none value.
template
@@ -134,5 +143,5 @@
for ( const auto & node : list ) {
count = -1;
- mapper( node )->accept( *visitor );
+ maybe_accept( mapper( node ) );
if ( count != -1 && count < minimum ) minimum = count;
}
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/SymTab/Autogen.h (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -21,4 +21,5 @@
#include "AST/Decl.hpp"
+#include "AST/Eval.hpp"
#include "AST/Expr.hpp"
#include "AST/Init.hpp"
@@ -264,5 +265,6 @@
}
- ast::ptr< ast::Expr > begin, end, cmp, update;
+ ast::ptr< ast::Expr > begin, end;
+ std::string cmp, update;
if ( forward ) {
@@ -270,14 +272,13 @@
begin = ast::ConstantExpr::from_int( loc, 0 );
end = array->dimension;
- cmp = new ast::NameExpr{ loc, "?" };
- update = new ast::NameExpr{ loc, "++?" };
+ cmp = "?";
+ update = "++?";
} else {
// generate: for ( int i = N-1; i >= 0; --i )
- begin = new ast::UntypedExpr{
- loc, new ast::NameExpr{ loc, "?-?" },
- { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } };
+ begin = ast::call(
+ loc, "?-?", array->dimension, ast::ConstantExpr::from_int( loc, 1 ) );
end = ast::ConstantExpr::from_int( loc, 0 );
- cmp = new ast::NameExpr{ loc, "?>=?" };
- update = new ast::NameExpr{ loc, "--?" };
+ cmp = "?>=?";
+ update = "--?";
}
@@ -285,18 +286,15 @@
loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
new ast::SingleInit{ loc, begin } };
-
- ast::ptr< ast::Expr > cond = new ast::UntypedExpr{
- loc, cmp, { new ast::VariableExpr{ loc, index }, end } };
-
- ast::ptr< ast::Expr > inc = new ast::UntypedExpr{
- loc, update, { new ast::VariableExpr{ loc, index } } };
-
- ast::ptr< ast::Expr > dstIndex = new ast::UntypedExpr{
- loc, new ast::NameExpr{ loc, "?[?]" },
- { dstParam, new ast::VariableExpr{ loc, index } } };
+ ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };
+
+ ast::ptr< ast::Expr > cond = ast::call( loc, cmp, indexVar, end );
+
+ ast::ptr< ast::Expr > inc = ast::call( loc, update, indexVar );
+
+ ast::ptr< ast::Expr > dstIndex = ast::call( loc, "?[?]", dstParam, indexVar );
// srcParam must keep track of the array indices to build the source parameter and/or
// array list initializer
- srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, array->dimension );
+ srcParam.addArrayIndex( indexVar, array->dimension );
// for stmt's body, eventually containing call
@@ -384,5 +382,5 @@
if ( isUnnamedBitfield( obj ) ) return {};
- ast::ptr< ast::Type > addCast = nullptr;
+ ast::ptr< ast::Type > addCast;
if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
assert( dstParam->result );
Index: src/Tuples/Explode.cc
===================================================================
--- src/Tuples/Explode.cc (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/Tuples/Explode.cc (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -129,5 +129,4 @@
for ( const ast::Expr * expr : tupleExpr->exprs ) {
exprs.emplace_back( applyCast( expr, false ) );
- //exprs.emplace_back( ast::ptr< ast::Expr >( applyCast( expr, false ) ) );
}
if ( first ) {
Index: src/Tuples/Explode.h
===================================================================
--- src/Tuples/Explode.h (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/Tuples/Explode.h (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -210,5 +210,5 @@
}
// Cast a reference away to a value-type to allow further explosion.
- if ( dynamic_cast< const ast::ReferenceType *>( local->result.get() ) ) {
+ if ( local->result.as< ast::ReferenceType >() ) {
local = new ast::CastExpr{ local, tupleType };
}
@@ -220,5 +220,4 @@
// delete idx;
}
- // delete local;
}
} else {
Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/Tuples/TupleAssignment.cc (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -465,5 +465,5 @@
// resolve ctor/dtor for the new object
ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit(
- InitTweak::genCtorInit( location, ret ), spotter.crntFinder.symtab );
+ InitTweak::genCtorInit( location, ret ), spotter.crntFinder.localSyms );
// remove environments from subexpressions of stmtExpr
ast::Pass< EnvRemover > rm{ env };
@@ -560,5 +560,5 @@
// resolve the cast expression so that rhsCand return type is bound by the cast
// type as needed, and transfer the resulting environment
- ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env };
+ ResolvExpr::CandidateFinder finder{ spotter.crntFinder.localSyms, env };
finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() );
assert( finder.candidates.size() == 1 );
@@ -609,5 +609,5 @@
// explode the LHS so that each field of a tuple-valued expr is assigned
ResolvExpr::CandidateList lhs;
- explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true );
+ explode( *lhsCand, crntFinder.localSyms, back_inserter(lhs), true );
for ( ResolvExpr::CandidateRef & cand : lhs ) {
// each LHS value must be a reference - some come in with a cast, if not
@@ -629,5 +629,5 @@
if ( isTuple( rhsCand->expr ) ) {
// multiple assignment
- explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true );
+ explode( *rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
matcher.reset(
new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
@@ -648,5 +648,5 @@
// multiple assignment
ResolvExpr::CandidateList rhs;
- explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true );
+ explode( rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
matcher.reset(
new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
@@ -678,5 +678,5 @@
)
- ResolvExpr::CandidateFinder finder{ crntFinder.symtab, matcher->env };
+ ResolvExpr::CandidateFinder finder{ crntFinder.localSyms, matcher->env };
try {
Index: src/main.cc
===================================================================
--- src/main.cc (revision 83b52f10c32ca12f8f96a9532884e06dd2d083dd)
+++ src/main.cc (revision 96ac72c02fbef1f5ea479906ac9e2c82cfc53309)
@@ -29,4 +29,5 @@
#include // for char_traits, operator<<
+#include "AST/Convert.hpp"
#include "CompilationState.h"
#include "../config.h" // for CFA_LIBDIR
@@ -302,5 +303,10 @@
} // if
- PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
+ // PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
+ {
+ auto transUnit = convert( move( translationUnit ) );
+ PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
+ translationUnit = convert( move( transUnit ) );
+ }
if ( exprp ) {
dump( translationUnit );