Changes in / [f7e4f8e8:b9537e6]


Ignore:
Files:
10 deleted
71 edited

Legend:

Unmodified
Added
Removed
  • Jenkinsfile

    rf7e4f8e8 rb9537e6  
    127127                        }
    128128
    129                         ast = Settings.NewAST ? "--enable-new-ast" : "--disable-new-ast"
    130 
    131                         sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} AR=gcc-ar RANLIB=gcc-ranlib ${targets} ${ast} --quiet --prefix=${BuildDir}"
     129                        sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} AR=gcc-ar RANLIB=gcc-ranlib ${targets} --quiet --prefix=${BuildDir}"
    132130
    133131                        // Configure libcfa
     
    361359        public final CC_Desc Compiler
    362360        public final Arch_Desc Architecture
    363         public final Boolean NewAST
    364361        public final Boolean RunAllTests
    365362        public final Boolean RunBenchmark
     
    413410
    414411                this.IsSandbox          = (branch == "jenkins-sandbox")
    415                 this.NewAST             = param.NewAST
    416412                this.RunAllTests        = param.RunAllTests
    417413                this.RunBenchmark       = param.RunBenchmark
     
    474470                                ],                                                                                              \
    475471                                [$class: 'BooleanParameterDefinition',                                                  \
    476                                         description: 'If true, build compiler using new AST',           \
    477                                         name: 'NewAST',                                                                         \
    478                                         defaultValue: false,                                                            \
    479                                 ],                                                                                              \
    480                                 [$class: 'BooleanParameterDefinition',                                                  \
    481472                                        description: 'If false, only the quick test suite is ran',              \
    482473                                        name: 'RunAllTests',                                                            \
    483474                                        defaultValue: false,                                                            \
    484                                 ],
     475                                ],                                                                                              \
    485476                                [$class: 'BooleanParameterDefinition',                                                  \
    486477                                        description: 'If true, jenkins also runs benchmarks',           \
  • doc/papers/concurrency/mail2

    rf7e4f8e8 rb9537e6  
    1 
    21Date: Wed, 26 Jun 2019 20:12:38 +0000
    32From: Aaron Thomas <onbehalfof@manuscriptcentral.com>
     
    10751074Software: Practice and Experience Editorial Office
    10761075
    1077 
    1078 
    1079 Date: Thu, 15 Oct 2020 13:48:52 +0000
    1080 From: Richard Jones <onbehalfof@manuscriptcentral.com>
    1081 Reply-To: R.E.Jones@kent.ac.uk
    1082 To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca
    1083 Subject: Software: Practice and Experience - Decision on Manuscript ID
    1084  SPE-19-0219.R3
    1085 
    1086 15-Oct-2020
    1087 
    1088 Dear Dr Buhr,
    1089 
    1090 It is a pleasure to accept your manuscript entitled "Advanced Control-flow and Concurrency in Cforall" in its current form for publication in Software: Practice and Experience. 
    1091 
    1092 Please note although the manuscript is accepted the files will now be checked to ensure that everything is ready for publication, and you may be contacted if final versions of files for publication are required.
    1093 
    1094 Your article cannot be published until the publisher has received the appropriate signed license agreement. Within the next few days the corresponding author will receive an email from Wiley's Author Services system which will ask them to log in and will present them with the appropriate license for completion.
    1095 
    1096 Thank you for your fine contribution.
    1097 
    1098 Sincerely,
    1099 Richard
    1100 
    1101 Prof. Richard Jones
    1102 Editor, Software: Practice and Experience
    1103 R.E.Jones@kent.ac.uk
    1104 
    1105 P.S. - You can help your research get the attention it deserves! Check out Wiley's free Promotion Guide for best-practice recommendations for promoting your work at www.wileyauthors.com/eeo/guide. And learn more about Wiley Editing Services which offers professional video, design, and writing services to create shareable video abstracts, infographics, conference posters, lay summaries, and research news stories for your research at www.wileyauthors.com/eeo/promotion.
    1106 
    1107 This journal accepts artwork submissions for Cover Images. This is an optional service you can use to help increase article exposure and showcase your research. For more information, including artwork guidelines, pricing, and submission details, please visit the Journal Cover Image page at www.wileyauthors.com/eeo/covers. If you want help creating an image, Wiley Editing Services offers a professional cover image design service that creates eye-catching images, ready to be showcased on the journal cover at www.wileyauthors.com/eeo/design.
    1108 
    1109 
    1110 
    1111 Date: Fri, 16 Oct 2020 12:44:42 +0000
    1112 From: Mayank Roy Chowdhury <onbehalfof@manuscriptcentral.com>
    1113 Reply-To: speoffice@wiley.com
    1114 To: pabuhr@uwaterloo.ca
    1115 Subject: Manuscript Accepted - Please submit final updates to SPE-19-0219.R3 [email ref: ENR-AW-1-c]
    1116 
    1117 16-Oct-2020
    1118 
    1119 Dear Dr. Buhr,
    1120 
    1121 Manuscript id: SPE-19-0219.R3
    1122 Manuscript title: Advanced Control-flow and Concurrency in Cforall
    1123 
    1124 Although your manuscript has been accepted for publication it is now being returned to your author center for you to review and make any final adjustments or corrections prior to production and publication.
    1125 
    1126 Any special instructions will be listed below:
    1127 1) Funding Information added in ScholorOne but missing in main document, Kindly add the Funding information in main document.
    1128 2) Please provide the clean version of the manuscript without any highlights or tracked changes.
    1129 3) Kindly check and make sure citations for all figures and Tables are present in the main document
    1130 
    1131 Please now log back into your Scholar One Author Center and click on the "Manuscripts Accepted for First Look" queue. In order to update the submission, click on the "submit updated manuscript" link in the "Actions" column and follow the steps as you would during a manuscript submission process.
    1132 
    1133 On the File Upload screen please upload the FINAL versions of all the files, including print quality image files. For information about image quality requirements, please refer to the guidelines at https://authorservices.wiley.com/asset/photos/electronic_artwork_guidelines.pdf.
    1134 
    1135 Instructions for uploading replacement files:
    1136 1. On the "File Upload" step, click on the "edit" button for the file you wish to replace.
    1137 2. In the "Upload a later version" section, browse to locate the replacement final version.
    1138 3. Add any comments concerning the replacement (e.g. "high res image").
    1139 4. Select whether the new file is a minor or major version (we suggest you select minor version)
    1140 5. Click upload.
    1141 6. Click 'Submit' when all the files have been uploaded and you will receive an automated email to say that submission is successful.
    1142 
    1143 Please submit your updates within the next 7 days to ensure there are no unnecessary delays in production.
    1144 
    1145 Sincerely,
    1146 Software: Practice and Experience Editorial Office
    1147 
    1148 
    1149 
    1150 From: SPE Office <speoffice@wiley.com>
    1151 To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
    1152 Subject: Re: Manuscript Accepted - Please submit final updates to SPE-19-0219.R3 [email ref: ENR-AW-1-c]
    1153 Date: Mon, 19 Oct 2020 17:04:24 +0000
    1154 
    1155 Dear Dr. Buhr,
    1156 
    1157 Thank you very much for contacting the Editorial Office.
    1158 
    1159 I would like to let you know that the files has been found in order and moved to production.
    1160 
    1161 Plesae let me know for further assistance in this regard.
    1162 
    1163 Best Regards
    1164 
    1165 Mayank Roy Chowdhury
    1166 Editorial Assistant
    1167 Software practice and Experience
    1168 ________________________________
    1169 From: Peter A. Buhr <pabuhr@uwaterloo.ca>
    1170 Sent: Sunday, October 18, 2020 2:00 PM
    1171 To: SPE Office <speoffice@wiley.com>
    1172 Cc: Thierry Delisle <tdelisle@uwaterloo.ca>
    1173 Subject: Re: Manuscript Accepted - Please submit final updates to SPE-19-0219.R3 [email ref: ENR-AW-1-c]
    1174 
    1175        This is an external email.
    1176 
    1177     Mayank Roy Chowdhury <onbehalfof@manuscriptcentral.com> writes:
    1178 
    1179     Instructions for uploading replacement files:
    1180     1. On the "File Upload" step, click on the "edit" button for the file you wish to replace.
    1181     2. In the "Upload a later version" section, browse to locate the replacement final version.
    1182     3. Add any comments concerning the replacement (e.g. "high res image").
    1183     4. Select whether the new file is a minor or major version (we suggest you select minor version)
    1184     5. Click upload.
    1185     6. Click 'Submit' when all the files have been uploaded and you will receive an automated email to say that submission is successful.
    1186 
    1187 There was no "edit" button on the "File Upload" page, so I just upload the
    1188 final version of the PDF and source files using the mechanism on the "File
    1189 Upload" page and submitted that.
    1190 
    1191 
    1192 
    1193 Date: Tue, 20 Oct 2020 13:28:37 +0530
    1194 To: "Dr. Peter Buhr" <pabuhr@uwaterloo.ca>
    1195 From: jpcms@spi-global.com
    1196 Subject: Information: Production Editor Contact Software:Practice and Experience  | Advanced Control-flow and Concurrency in C A
    1197 
    1198 Dear Dr. Peter Buhr,
    1199 
    1200 We are in the process of preparing "Advanced Control-flow and Concurrency in C A" for publication. Your production editor, Joel Pacaanas, will support you and your article throughout the process.
    1201 
    1202 Please get in touch with your Production Editor at SPEproofs@wiley.com;EllaMae.Navor@spi-global.com if you have any questions.
    1203                
    1204 Sincerely,
    1205 Booking-in Team,
    1206 On behalf of Wiley
    1207 
    1208 Article ID: SPE_2925
    1209 Article DOI: 10.1002/SPE.2925
    1210 
    1211 
    1212 
    1213 Date: Tue, 20 Oct 2020 10:33:04 +0000
    1214 From: <cs-author@wiley.com>
    1215 To: <pabuhr@uwaterloo.ca>
    1216 Subject: In Production: Your article accepted in Software: Practice and Experience
    1217 
    1218 Dear Peter Buhr,
    1219 
    1220 Article ID: SPE2925
    1221 Article DOI: 10.1002/spe.2925
    1222 Internal Article ID: 16922213
    1223 Article: Advanced Control-flow and Concurrency in C A
    1224 Journal: Software: Practice and Experience
    1225 
    1226 Congratulations on the acceptance of your article for publication in Software: Practice and Experience.
    1227 
    1228 Your article has been received and the production process is now underway. We look forward to working with you and publishing your article. Using Wiley Author Services, you can track your article's progress.
    1229 
    1230 Please click below to login - if you are using a different email address than this one, you will need to manually assign this article to your Dashboard (see https://hub.wiley.com/docs/support/assigning-a-missing-article-to-my-dashboard-DOC-11871?utm_source=new%20user%20invitation&utm_medium=email How do I assign a missing article to My Dashboard?):
    1231 
    1232 https://authorservices.wiley.com/index.html#login?campaign=email_invitation-new
    1233 
    1234 If applicable, a list of available actions will appear below - check out your Author Services Dashboard for all actions related to your articles.
    1235 
    1236 Sign your license agreement (REQUIRED)  -- you will receive an email when this task is ready on your dashboard. Track your article's progress to publicationAccess your published articleInvite colleagues to view your published article
    1237 If you need any assistance, please click http://www.wileyauthors.com/help?utm_source=new%20user%20invitation&utm_medium=email here to view our Help section.
    1238 
    1239 Sincerely,
    1240 Wiley Author Services
    1241 
    1242 P.S. - Some journals accept artwork submissions for Cover Images. This is an optional service you can use to help increase article exposure and showcase your research. Pricing and placement options vary by journal. For more information, including artwork guidelines, pricing, and submission details, please visit the https://authorservices.wiley.com/author-resources/Journal-Authors/Promotion/journal-cover-image.html?utm_source=as&utm_medium=email&utm_term=invitation_msg&utm_content=covers&utm_campaign=2019feb?campaign=email_invitation-new" target=_blank">Journal Cover Image page. If you want help creating an image, Wiley Editing Services offers a professional https://wileyeditingservices.com/en/article-promotion/cover-image-design.html?utm_source=as&utm_medium=email&utm_term=ie&utm_content=cid&utm_campaign=prodops" target=_blank">Cover Image Design service that creates eye-catching images, ready to be showcased on the journal cover.
    1243 
    1244 
    1245 
    1246 Date: Thu, 22 Oct 2020 20:21:49 +0000
    1247 From: <cs-author@wiley.com>
    1248 To: <pabuhr@uwaterloo.ca>
    1249 Subject: You have actions to complete in Author Services
    1250 
    1251 Dear Peter Buhr,
    1252 
    1253 Article ID: SPE2925
    1254 Article DOI: 10.1002/spe.2925
    1255 Internal Article ID: 16922213
    1256 Article: Advanced Control-flow and Concurrency in C A
    1257 Journal: Software: Practice and Experience
    1258 
    1259 For the above article, you have the following open tasks:
    1260 
    1261 Sign your license agreement in order to publish your article. Simply click the Sign License button on your https://authorservices.wiley.com?campaign=email_license-notice1">Wiley Author Services Dashboard.
    1262 
    1263 Need any help? Please visit our https://authorsupport.wiley.com/s/">Author Support Center.
    1264 
    1265 Sincerely,
    1266 Wiley Author Services
    1267 
    1268 
    1269 
    1270 Date: Thu, 22 Oct 2020 23:13:07 +0000
    1271 From: <cs-author@wiley.com>
    1272 To: <pabuhr@uwaterloo.ca>
    1273 Subject: License was successfully submitted! Thank you!
    1274 
    1275 Dear Peter Buhr,                                                                 
    1276 
    1277 Article ID: SPE2925
    1278 Article DOI: 10.1002/spe.2925
    1279 Internal Article ID: 16922213
    1280 Article: Advanced Control-flow and Concurrency in C A 
    1281 Journal: Software: Practice and Experience                                                                     
    1282                                                                          
    1283 You've successfully completed license signing for your article - thank you! You can view your signed agreement at any time by visiting your https://authorservices.wiley.com?campaign=email_license-confirm">Wiley Author Services Dashboard.                                                                     
    1284 
    1285 Sincerely,                                                                                 
    1286 
    1287 Wiley Author Services
  • doc/proposals/vtable.md

    rf7e4f8e8 rb9537e6  
    512512possibly like the one used to create the assertion.
    513513
    514 ### Extension: Associated Types Use
    515 If the `associated_types.md` proposal is accepted the following trait could
    516 be added:
    517 
    518     trait is_virtual(dtype T) {
    519         dtype table;
    520         // An example assertion:
    521         const table & get_virtual_table(T &);
    522     }
    523 
    524 There may be more assertions but there has to be at least one way to find
    525 the (possibly default) virtual table. It is required to construct instances
    526 of the type.
    527 
    528 Without the assotiated type it would look like this:
    529 
    530     trait is_virtual(dtype T, dtype table) {
    531         const table & get_virtual_table(T &);
    532     }
    533 
    534 Which is just a little bit longer to use but becomes more problematic if the
    535 user has to explicately provide the table's name as it doesn't really have its
    536 own type name. If it does it is probably mangled.
    537 
    538514### Virtual Tables as Types
    539515Here we consider encoding plus the implementation of functions on it to be a
  • doc/theses/andrew_beach_MMath/thesis-frontpgs.tex

    rf7e4f8e8 rb9537e6  
    55% TITLE PAGE
    66%----------------------------------------------------------------------
    7 
    8 % Slowly generalizing.
    9 \ethesissetup{
    10   author=Pat Neugraad,%
    11   title={University of Waterloo E-Thesis Template for \LaTeX},
    12   degree=phd,%
    13   program=Zoology,%
    14 }
    157
    168\pagestyle{empty}
     
    2315        \vspace*{1.0cm}
    2416
    25         {\Huge\bf \eprint{title}}
    26 
    27         \vspace*{1.0cm}
    28 
     17        \Huge
     18        {\bf University of Waterloo E-Thesis Template for \LaTeX }
     19
     20        \vspace*{1.0cm}
     21
     22        \normalsize
    2923        by \\
    3024
    3125        \vspace*{1.0cm}
    3226
    33         {\Large \eprint{author}} \\
     27        \Large
     28        Pat Neugraad \\
    3429
    3530        \vspace*{3.0cm}
    3631
     32        \normalsize
    3733        A thesis \\
    3834        presented to the University of Waterloo \\
    3935        in fulfillment of the \\
    4036        thesis requirement for the degree of \\
    41         \eprint{degree} \\
     37        Doctor of Philosophy \\
    4238        in \\
    43         \eprint{program} \\
     39        Zoology \\
    4440
    4541        \vspace*{2.0cm}
     
    4945        \vspace*{1.0cm}
    5046
    51         \copyright{} \eprint{author} 2017 \\
     47        \copyright\ Pat Neugraad 2017 \\
    5248        \end{center}
    5349\end{titlepage}
  • doc/theses/andrew_beach_MMath/uw-ethesis.cls

    rf7e4f8e8 rb9537e6  
    1919%
    2020% Exported Names:
    21 %   \ethesissetup{<key-value-pairs>}
    22 %     Preforms set-up (or a reconfiguration) of the document class. See the
    23 %     Set-Up Keys section for the keys that may be passed in. Use commas to
    24 %     seperate key-value-pairs.
    25 %
    2621%   \ifformat{<format>}{<true>}{<false>}
    2722%     If the document's format is <format> than expands to <true> otherwise
     
    3227%     initial setup depends on the document format but they can be overriden
    3328%     with options in <setup> (set hyperref's \hypersetup for details).
    34 %
    35 %   \eprint{<key>}
    36 %     Expands to a human readable value tracked by the ethesis class. This
    37 %     can be used to retreave and format values set during set up.
    38 %
    39 % Set-Up Keys:
    40 %   author=<text>
    41 %   title=<text>
    42 %   program=<text>
    43 %   subject=<text>
    44 %   keywords=<text>
    45 %   degree=masters|phd
    46 %   faculty=ahs|arts|eng|env|math|sci
    4729\NeedsTeXFormat{LaTeX2e}
    48 \ProvidesClass{uw-ethesis}[2020/10/25 v0.2 UW-eThesis Template Document Class]
     30\ProvidesClass{uw-ethesis}[2020/03/24 v0.1 UW-eThesis Template Document Class]
    4931
    5032\RequirePackage{etoolbox}
    51 \RequirePackage{xkeyval}
    5233
    5334% Requested Format:
    54 \newrobustcmd*{\ethesis@@format}{digital}
    55 \DeclareOption{print}{\renewrobustcmd*{\ethesis@@format}{print}}
    56 \DeclareOption{digital}{\renewrobustcmd*{\ethesis@@format}{digital}}
     35\newrobustcmd*{\ethesis@format}{digital}
     36\DeclareOption{print}{\renewrobustcmd*{\ethesis@format}{print}}
     37\DeclareOption{digital}{\renewrobustcmd*{\ethesis@format}{digital}}
    5738
    5839\ProcessOptions\relax
     
    10081% a recto page. This will often require an empty verso (left-hand side) page
    10182% that should not have the page number printed on it.
    102 \let\ethesis@origdoublepage\cleardoublepage
     83\let\origdoublepage\cleardoublepage
    10384\newcommand{\clearemptydoublepage}{%
    104   \clearpage{\pagestyle{empty}\ethesis@origdoublepage}}
     85  \clearpage{\pagestyle{empty}\origdoublepage}}
    10586\let\cleardoublepage\clearemptydoublepage
    10687
     
    10889\renewcommand*{\bibname}{References}
    10990
    110 \newrobustcmd*\ethesissetup[1]{\setkeys{ethesis}{#1}}
    111 
    112 \define@cmdkeys{ethesis}[ethesis@@]{%
    113   author,title,program,subject,keywords}
    114 
    115 \define@choicekey{ethesis}{degree}{masters,phd}{\def\ethesis@@degree{#1}}
    116 \define@choicekey{ethesis}{faculty}{ahs,arts,eng,env,math,sci}%
    117   {\def\ethesis@@faculty{#1}}
    118 
    119 \newrobustcmd*\eprint[1]{
    120   \ifcsdef{ethesis@long#1}{\csuse{ethesis@long#1}}{%
    121     \ifcsdef{ethesis@@#1}{\csuse{ethesis@@#1}}{%
    122       % ERROR: (Check for a way to emit an actual error.)
    123       [UW-eThesis doesn't know how to print: #1 ]
    124     }
    125   }
    126 }
    127 
    128 \newrobustcmd*\ethesis@longdegree{%
    129   \ifdefstring{\ethesis@@degree}{phd}{Doctor of Philosophy}{Masters}}
     91% Configurations
     92\def\setThesisTitle#1{\newrobustcmd*{\ethesis@title}{#1}}
     93\def\setThesisAuthor#1{\newrobustcmd*{\ethesis@author}{#1}}
     94\def\setThesisSubject#1{\newrobustcmd*{\ethesis@subject}{#1}}
     95\def\setThesisKeywords#1{\newrobustcmd*{\ethesis@keywords}{#1}}
    13096
    13197% Includes the hyperref package loading a number of defaults.
     
    140106    pdfstartview={FitH},    % Fits the width of the page to the window.
    141107  }
    142   \ifdef{\ethesis@@title}{\hypersetup{pdftitle={\ethesis@@title}}}{}
    143   \ifdef{\ethesis@@author}{\hypersetup{pdfauthor={\ethesis@@author}}}{}
    144   \ifdef{\ethesis@@subject}{\hypersetup{pdfsubject={\ethesis@@subject}}}{}
    145   \ifdef{\ethesis@@keywords}{\hypersetup{pdfkeywords={\ethesis@@keywords}}}{}
     108  \ifdef{\ethesis@title}{\hypersetup{pdftitle={\ethesis@title}}}{}
     109  \ifdef{\ethesis@author}{\hypersetup{pdfauthor={\ethesis@author}}}{}
     110  \ifdef{\ethesis@subject}{\hypersetup{pdfsubject={\ethesis@subject}}}{}
     111  \ifdef{\ethesis@keywords}{\hypersetup{pdfkeywords={\ethesis@keywords}}}{}
    146112  \ifformat{print}{
    147113    \hypersetup{
  • libcfa/prelude/builtins.c

    rf7e4f8e8 rb9537e6  
    99// Author           : Peter A. Buhr
    1010// Created On       : Fri Jul 21 16:21:03 2017
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct 27 14:42:00 2020
    13 // Update Count     : 111
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Oct  9 18:26:19 2020
     13// Update Count     : 110
    1414//
    15 
    16 #define __cforall_builtins__
    1715
    1816// type that wraps a pointer and a destructor-like function - used in generating implicit destructor calls for struct members in user-defined functions
  • libcfa/src/concurrency/coroutine.cfa

    rf7e4f8e8 rb9537e6  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Oct 23 23:05:24 2020
    13 // Update Count     : 22
     12// Last Modified On : Tue May 26 22:06:09 2020
     13// Update Count     : 21
    1414//
    1515
     
    2424#include <unistd.h>
    2525#include <sys/mman.h>                                                                   // mprotect
     26extern "C" {
     27// use this define to make unwind.h play nice, definitely a hack
     28#define HIDE_EXPORTS
    2629#include <unwind.h>
     30#undef HIDE_EXPORTS
     31}
    2732
    2833#include "kernel_private.hfa"
    29 #include "exception.hfa"
    3034
    3135#define __CFA_INVOKE_PRIVATE__
     
    4549FORALL_DATA_INSTANCE(CoroutineCancelled, (dtype coroutine_t), (coroutine_t))
    4650
     51struct __cfaehm_node {
     52        struct _Unwind_Exception unwind_exception;
     53        struct __cfaehm_node * next;
     54        int handler_index;
     55};
     56
    4757forall(dtype T)
    4858void mark_exception(CoroutineCancelled(T) *) {}
     
    5060forall(dtype T)
    5161void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) {
    52         dst->virtual_table = src->virtual_table;
    5362        dst->the_coroutine = src->the_coroutine;
    5463        dst->the_exception = src->the_exception;
     
    6574        verify( desc->cancellation );
    6675        desc->state = Cancelled;
    67         exception_t * except = __cfaehm_cancellation_exception( desc->cancellation );
     76        exception_t * except = (exception_t *)(1 + (__cfaehm_node *)desc->cancellation);
    6877
    6978        // TODO: Remove explitate vtable set once trac#186 is fixed.
     
    208217                size = libFloor(create_size - stack_data_size - diff, libAlign());
    209218        } // if
    210         assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %zd bytes for a stack.", size, MinStackSize );
     219        assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %d bytes for a stack.", size, MinStackSize );
    211220
    212221        this->storage = (__stack_t *)((intptr_t)storage + size);
  • libcfa/src/concurrency/exception.cfa

    rf7e4f8e8 rb9537e6  
    1010// Created On       : Mon Aug 17 10:41:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Oct 28 14:34:00 2020
    13 // Update Count     : 1
     12// Last Modified On : Tue Aug 25 14:41:00 2020
     13// Update Count     : 0
    1414//
    1515
    16 #define __cforall_thread__
     16extern "C" {
     17// use this define to make unwind.h play nice, definitely a hack
     18#define HIDE_EXPORTS
     19#include <unwind.h>
     20#undef HIDE_EXPORTS
     21}
    1722
     23#include "invoke.h"
    1824#include "exception.hfa"
    19 
    2025#include "coroutine.hfa"
    2126
    2227extern struct $thread * mainThread;
    23 extern "C" {
    24 extern void __cfactx_thrd_leave();
    25 }
    2628
    2729// Common pattern for all the stop functions, wait until the end then act.
     
    5052
    5153STOP_AT_END_FUNCTION(thread_cancelstop,
    52         __cfactx_thrd_leave();
    53         __cabi_abort( "Resumed cancelled thread" );
     54        // TODO: Instead pass information to the joiner.
     55        abort();
    5456)
    5557
     
    8385                stop_param = (void *)0x22;
    8486        } else {
    85                 this_thread->self_cor.cancellation = unwind_exception;
    86 
    8787                stop_func = thread_cancelstop;
    8888                stop_param = this_thread;
  • libcfa/src/concurrency/exception.hfa

    rf7e4f8e8 rb9537e6  
    1616#pragma once
    1717
    18 // This is an internal bridge between the two modes and must be C compatable.
    19 
    20 #include <unwind.h>
    2118#include "bits/defs.hfa"
    2219#include "invoke.h"
    23 #include "exception.h"
    2420
    2521#ifdef __cforall
    2622extern "C" {
     23
     24#define HIDE_EXPORTS
    2725#endif
     26#include "unwind.h"
    2827
    2928struct exception_context_t * this_exception_context(void) OPTIONAL_THREAD;
     
    3332
    3433#ifdef __cforall
     34#undef HIDE_EXPORTS
    3535}
    3636#endif
  • libcfa/src/concurrency/invoke.h

    rf7e4f8e8 rb9537e6  
    157157
    158158                // current execution status for coroutine
    159                 // Possible values are:
    160                 //    - TICKET_BLOCKED (-1) thread is blocked
    161                 //    - TICKET_RUNNING ( 0) thread is running
    162                 //    - TICKET_UNBLOCK ( 1) thread should ignore next block
    163159                volatile int ticket;
    164160                enum __Coroutine_State state:8;
  • libcfa/src/concurrency/io/setup.cfa

    rf7e4f8e8 rb9537e6  
    250250                                        // Fixup the thread state
    251251                                        thrd.state = Blocked;
    252                                         thrd.ticket = TICKET_BLOCKED;
     252                                        thrd.ticket = 0;
    253253                                        thrd.preempted = __NO_PREEMPTION;
    254254
  • libcfa/src/concurrency/kernel.cfa

    rf7e4f8e8 rb9537e6  
    252252                /* paranoid */ verify( kernelTLS.this_thread == thrd_dst );
    253253                /* paranoid */ verify( thrd_dst->context.SP );
    254                 /* paranoid */ verify( thrd_dst->state != Halted );
    255254                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor
    256255                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor
     
    288287                if(unlikely(thrd_dst->state == Halted)) {
    289288                        // The thread has halted, it should never be scheduled/run again
    290                         // finish the thread
    291                         __thread_finish( thrd_dst );
     289                        // We may need to wake someone up here since
     290                        unpark( this->destroyer );
     291                        this->destroyer = 0p;
    292292                        break RUNNING;
    293293                }
     
    299299                int old_ticket = __atomic_fetch_sub(&thrd_dst->ticket, 1, __ATOMIC_SEQ_CST);
    300300                switch(old_ticket) {
    301                         case TICKET_RUNNING:
     301                        case 1:
    302302                                // This is case 1, the regular case, nothing more is needed
    303303                                break RUNNING;
    304                         case TICKET_UNBLOCK:
     304                        case 2:
    305305                                // This is case 2, the racy case, someone tried to run this thread before it finished blocking
    306306                                // In this case, just run it again.
     
    410410        int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST);
    411411        switch(old_ticket) {
    412                 case TICKET_RUNNING:
     412                case 1:
    413413                        // Wake won the race, the thread will reschedule/rerun itself
    414414                        break;
    415                 case TICKET_BLOCKED:
     415                case 0:
    416416                        /* paranoid */ verify( ! thrd->preempted != __NO_PREEMPTION );
    417417                        /* paranoid */ verify( thrd->state == Blocked );
     
    422422                default:
    423423                        // This makes no sense, something is wrong abort
    424                         abort("Thread %p (%s) has mismatch park/unpark\n", thrd, thrd->self_cor.name);
     424                        abort();
    425425        }
    426426}
     
    448448}
    449449
    450 extern "C" {
    451         // Leave the thread monitor
    452         // last routine called by a thread.
    453         // Should never return
    454         void __cfactx_thrd_leave() {
    455                 $thread * thrd = TL_GET( this_thread );
    456                 $monitor * this = &thrd->self_mon;
    457 
    458                 // Lock the monitor now
    459                 lock( this->lock __cfaabi_dbg_ctx2 );
    460 
    461                 disable_interrupts();
    462 
    463                 thrd->state = Halted;
    464 
    465                 if( thrd != this->owner || this->recursion != 1) { abort( "Thread internal monitor has unbalanced recursion" ); }
    466 
    467                 // Leave the thread
    468                 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    469                 returnToKernel();
    470                 abort();
    471 
    472                 // Control flow should never reach here!
    473         }
     450// KERNEL ONLY
     451void __leave_thread() {
     452        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     453        returnToKernel();
     454        abort();
    474455}
    475456
  • libcfa/src/concurrency/kernel.hfa

    rf7e4f8e8 rb9537e6  
    7979        // Handle to pthreads
    8080        pthread_t kernel_thread;
     81
     82        // RunThread data
     83        // Action to do after a thread is ran
     84        $thread * destroyer;
    8185
    8286        // Preemption data
  • libcfa/src/concurrency/kernel/startup.cfa

    rf7e4f8e8 rb9537e6  
    441441
    442442static void ?{}( $thread & this, current_stack_info_t * info) with( this ) {
    443         ticket = TICKET_RUNNING;
     443        ticket = 1;
    444444        state = Start;
    445445        self_cor{ info };
     
    474474        this.cltr = &_cltr;
    475475        full_proc = true;
     476        destroyer = 0p;
    476477        do_terminate = false;
    477478        preemption_alarm = 0p;
  • libcfa/src/concurrency/kernel_private.hfa

    rf7e4f8e8 rb9537e6  
    3939;
    4040
    41 //release/wake-up the following resources
    42 void __thread_finish( $thread * thrd );
     41//Block current thread and release/wake-up the following resources
     42void __leave_thread() __attribute__((noreturn));
    4343
    4444//-----------------------------------------------------------------------------
     
    6565// KERNEL ONLY unpark with out disabling interrupts
    6666void __unpark( struct __processor_id_t *, $thread * thrd );
    67 
    68 #define TICKET_BLOCKED (-1) // thread is blocked
    69 #define TICKET_RUNNING ( 0) // thread is running
    70 #define TICKET_UNBLOCK ( 1) // thread should ignore next block
    7167
    7268static inline bool __post(single_sem & this, struct __processor_id_t * id) {
  • libcfa/src/concurrency/monitor.cfa

    rf7e4f8e8 rb9537e6  
    281281}
    282282
    283 void __thread_finish( $thread * thrd ) {
    284         $monitor * this = &thrd->self_mon;
    285 
    286         // Lock the monitor now
    287         /* paranoid */ verify( this->lock.lock );
    288         /* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
    289         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    290         /* paranoid */ verify( thrd->state == Halted );
    291         /* paranoid */ verify( this->recursion == 1 );
    292 
    293         // Leaving a recursion level, decrement the counter
    294         this->recursion -= 1;
    295         this->owner = 0p;
    296 
    297         // Fetch the next thread, can be null
    298         $thread * new_owner = next_thread( this );
    299 
    300         // Release the monitor lock
    301         unlock( this->lock );
    302 
    303         // Unpark the next owner if needed
    304         /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
    305         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    306         /* paranoid */ verify( thrd->state == Halted );
    307         unpark( new_owner );
     283extern "C" {
     284        // Leave the thread monitor
     285        // last routine called by a thread.
     286        // Should never return
     287        void __cfactx_thrd_leave() {
     288                $thread * thrd = TL_GET( this_thread );
     289                $monitor * this = &thrd->self_mon;
     290
     291                // Lock the monitor now
     292                lock( this->lock __cfaabi_dbg_ctx2 );
     293
     294                disable_interrupts();
     295
     296                thrd->state = Halted;
     297
     298                /* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
     299
     300                // Leaving a recursion level, decrement the counter
     301                this->recursion -= 1;
     302
     303                // If we haven't left the last level of recursion
     304                // it must mean there is an error
     305                if( this->recursion != 0) { abort( "Thread internal monitor has unbalanced recursion" ); }
     306
     307                // Fetch the next thread, can be null
     308                $thread * new_owner = next_thread( this );
     309
     310                // Release the monitor lock
     311                unlock( this->lock );
     312
     313                // Unpark the next owner if needed
     314                /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
     315                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     316                /* paranoid */ verify( ! kernelTLS.this_processor->destroyer );
     317                /* paranoid */ verify( thrd->state == Halted );
     318
     319                kernelTLS.this_processor->destroyer = new_owner;
     320
     321                // Leave the thread
     322                __leave_thread();
     323
     324                // Control flow should never reach here!
     325        }
     326}
     327
     328// Join a thread
     329forall( dtype T | is_thread(T) )
     330T & join( T & this ) {
     331        $monitor *    m = get_monitor(this);
     332        void (*dtor)(T& mutex this) = ^?{};
     333        monitor_dtor_guard_t __guard = { &m, (fptr_t)dtor, true };
     334        {
     335                return this;
     336        }
    308337}
    309338
  • libcfa/src/concurrency/thread.cfa

    rf7e4f8e8 rb9537e6  
    1919
    2020#include "kernel_private.hfa"
    21 #include "exception.hfa"
    2221
    2322#define __CFA_INVOKE_PRIVATE__
     
    2928        context{ 0p, 0p };
    3029        self_cor{ name, storage, storageSize };
    31         ticket = TICKET_RUNNING;
     30        ticket = 1;
    3231        state = Start;
    3332        preempted = __NO_PREEMPTION;
     
    5756        unregister(curr_cluster, this);
    5857        ^self_cor{};
    59 }
    60 
    61 FORALL_DATA_INSTANCE(ThreadCancelled, (dtype thread_t), (thread_t))
    62 
    63 forall(dtype T)
    64 void copy(ThreadCancelled(T) * dst, ThreadCancelled(T) * src) {
    65         dst->virtual_table = src->virtual_table;
    66         dst->the_thread = src->the_thread;
    67         dst->the_exception = src->the_exception;
    68 }
    69 
    70 forall(dtype T)
    71 const char * msg(ThreadCancelled(T) *) {
    72         return "ThreadCancelled";
    73 }
    74 
    75 forall(dtype T)
    76 static void default_thread_cancel_handler(ThreadCancelled(T) & ) {
    77         abort( "Unhandled thread cancellation.\n" );
    78 }
    79 
    80 forall(dtype T | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)))
    81 void ?{}( thread_dtor_guard_t & this,
    82                 T & thrd, void(*defaultResumptionHandler)(ThreadCancelled(T) &)) {
    83         $monitor * m = get_monitor(thrd);
    84         void (*dtor)(T& mutex this) = ^?{};
    85         bool join = defaultResumptionHandler != (void(*)(ThreadCancelled(T)&))0;
    86         (this.mg){&m, (void(*)())dtor, join};
    87 
    88         // After the guard set-up and any wait, check for cancellation.
    89         $thread * desc = get_thread(thrd);
    90         struct _Unwind_Exception * cancellation = desc->self_cor.cancellation;
    91         if ( likely( 0p == cancellation ) ) {
    92                 return;
    93         } else if ( Cancelled == desc->state ) {
    94                 return;
    95         }
    96         desc->state = Cancelled;
    97         if (!join) {
    98                 defaultResumptionHandler = default_thread_cancel_handler;
    99         }
    100 
    101         ThreadCancelled(T) except;
    102         // TODO: Remove explitate vtable set once trac#186 is fixed.
    103         except.virtual_table = &get_exception_vtable(&except);
    104         except.the_thread = &thrd;
    105         except.the_exception = __cfaehm_cancellation_exception( cancellation );
    106         throwResume except;
    107 
    108         except.the_exception->virtual_table->free( except.the_exception );
    109         free( cancellation );
    110         desc->self_cor.cancellation = 0p;
    111 }
    112 
    113 void ^?{}( thread_dtor_guard_t & this ) {
    114         ^(this.mg){};
    11558}
    11659
     
    15093}
    15194
    152 //-----------------------------------------------------------------------------
    153 forall(dtype T | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)))
    154 T & join( T & this ) {
    155         thread_dtor_guard_t guard = { this, defaultResumptionHandler };
    156         return this;
    157 }
    158 
    15995// Local Variables: //
    16096// mode: c //
  • libcfa/src/concurrency/thread.hfa

    rf7e4f8e8 rb9537e6  
    2222#include "kernel.hfa"
    2323#include "monitor.hfa"
    24 #include "exception.hfa"
    2524
    2625//-----------------------------------------------------------------------------
    2726// thread trait
    2827trait is_thread(dtype T) {
    29         void ^?{}(T& mutex this);
    30         void main(T& this);
    31         $thread* get_thread(T& this);
     28      void ^?{}(T& mutex this);
     29      void main(T& this);
     30      $thread* get_thread(T& this);
    3231};
    33 
    34 FORALL_DATA_EXCEPTION(ThreadCancelled, (dtype thread_t), (thread_t)) (
    35         thread_t * the_thread;
    36         exception_t * the_exception;
    37 );
    38 
    39 forall(dtype T)
    40 void copy(ThreadCancelled(T) * dst, ThreadCancelled(T) * src);
    41 
    42 forall(dtype T)
    43 const char * msg(ThreadCancelled(T) *);
    4432
    4533// define that satisfies the trait without using the thread keyword
     
    7765static inline void ?{}($thread & this, const char * const name, struct cluster & cl )                   { this{ name, cl, 0p, 65000 }; }
    7866static inline void ?{}($thread & this, const char * const name, struct cluster & cl, size_t stackSize ) { this{ name, cl, 0p, stackSize }; }
    79 
    80 struct thread_dtor_guard_t {
    81         monitor_dtor_guard_t mg;
    82 };
    83 
    84 forall( dtype T | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)) )
    85 void ?{}( thread_dtor_guard_t & this, T & thrd, void(*)(ThreadCancelled(T) &) );
    86 void ^?{}( thread_dtor_guard_t & this );
    8767
    8868//-----------------------------------------------------------------------------
     
    128108//----------
    129109// join
    130 forall( dtype T | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)) )
     110forall( dtype T | is_thread(T) )
    131111T & join( T & this );
    132112
  • libcfa/src/exception.c

    rf7e4f8e8 rb9537e6  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:13:00 2017
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct 27 16:27:00 2020
    13 // Update Count     : 35
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Aug 29 15:52:22 2020
     13// Update Count     : 34
    1414//
    1515
     
    1717#include <stddef.h> // for size_t
    1818
    19 #include <unwind.h> // for struct _Unwind_Exception {...};
    20 
    2119#include "exception.h"
    2220
    2321#include <stdlib.h>
    2422#include <stdio.h>
     23#include <unwind.h>
    2524#include <bits/debug.hfa>
    2625#include "concurrency/invoke.h"
     
    114113
    115114// MEMORY MANAGEMENT =========================================================
     115
     116struct __cfaehm_node {
     117        struct _Unwind_Exception unwind_exception;
     118        struct __cfaehm_node * next;
     119        int handler_index;
     120};
    116121
    117122#define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node)))
  • libcfa/src/exception.h

    rf7e4f8e8 rb9537e6  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // exception.h -- Internal exception handling definitions.
     7// exception.h -- Builtins for exception handling.
    88//
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:11:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct 27 14:45:00 2020
    13 // Update Count     : 11
     12// Last Modified On : Tue May 19 14:17:00 2020
     13// Update Count     : 10
    1414//
    1515
    1616#pragma once
    1717
    18 // This could be considered several headers. All are internal to the exception
    19 // system but needed to depending on whether they are C/Cforall code and
    20 // whether or not they are part of the builtins.
    2118
    2219#ifdef __cforall
    2320extern "C" {
    2421#endif
    25 
    26 // Included in C code or the built-ins.
    27 #if !defined(__cforall) || defined(__cforall_builtins__)
    2822
    2923struct __cfaehm_base_exception_t;
     
    5347// Function catches termination exceptions.
    5448void __cfaehm_try_terminate(
    55         void (*try_block)(),
    56         void (*catch_block)(int index, exception_t * except),
    57         int (*match_block)(exception_t * except));
     49    void (*try_block)(),
     50    void (*catch_block)(int index, exception_t * except),
     51    int (*match_block)(exception_t * except));
    5852
    5953// Clean-up the exception in catch blocks.
     
    6256// Data structure creates a list of resume handlers.
    6357struct __cfaehm_try_resume_node {
    64         struct __cfaehm_try_resume_node * next;
    65         _Bool (*handler)(exception_t * except);
     58    struct __cfaehm_try_resume_node * next;
     59    _Bool (*handler)(exception_t * except);
    6660};
    6761
    6862// These act as constructor and destructor for the resume node.
    6963void __cfaehm_try_resume_setup(
    70         struct __cfaehm_try_resume_node * node,
    71         _Bool (*handler)(exception_t * except));
     64    struct __cfaehm_try_resume_node * node,
     65    _Bool (*handler)(exception_t * except));
    7266void __cfaehm_try_resume_cleanup(
    73         struct __cfaehm_try_resume_node * node);
     67    struct __cfaehm_try_resume_node * node);
    7468
    7569// Check for a standard way to call fake deconstructors.
    7670struct __cfaehm_cleanup_hook {};
    7771
    78 #endif
    79 
    80 // Included in C code and the library.
    81 #if !defined(__cforall) || !defined(__cforall_builtins__)
    82 struct __cfaehm_node {
    83         struct _Unwind_Exception unwind_exception;
    84         struct __cfaehm_node * next;
    85         int handler_index;
    86 };
    87 
    88 static inline exception_t * __cfaehm_cancellation_exception(
    89                 struct _Unwind_Exception * unwind_exception ) {
    90         return (exception_t *)(1 + (struct __cfaehm_node *)unwind_exception);
    91 }
    92 #endif
    93 
    9472#ifdef __cforall
    9573}
    96 
    97 // Built-ins not visible in C.
    98 #if defined(__cforall_builtins__)
    9974
    10075// Not all the built-ins can be expressed in C. These can't be
     
    149124
    150125#endif
    151 
    152 #endif
  • src/AST/Convert.cpp

    rf7e4f8e8 rb9537e6  
    4747
    4848//================================================================================================
    49 namespace ast {
     49namespace {
    5050
    5151// This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not)
    5252// allow us to use the same stratagy in the new ast.
    53 // xxx - since convert back pass works, this concern seems to be unnecessary.
    54 
    55 // these need to be accessed in new FixInit now
    5653ast::Type * sizeType = nullptr;
    5754ast::FunctionDecl * dereferenceOperator = nullptr;
     
    6663        using Cache = std::unordered_map< const ast::Node *, BaseSyntaxNode * >;
    6764        Cache cache;
    68 
    69         // Statements can no longer be shared.
    70         // however, since StmtExprResult is now implemented, need to still maintain
    71         // readonly references.
    72         Cache readonlyCache;
    7365
    7466        template<typename T>
     
    162154        }
    163155
    164         const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {       
     156        const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {
     157                auto&& bfwd = get<Expression>().accept1( node->bitfieldWidth );
     158                auto&& type = get<Type>().accept1( node->type );
     159                auto&& init = get<Initializer>().accept1( node->init );
     160                auto&& attr = get<Attribute>().acceptL( node->attributes );
    165161                if ( inCache( node ) ) {
    166162                        return nullptr;
    167163                }
    168                 auto bfwd = get<Expression>().accept1( node->bitfieldWidth );
    169                 auto type = get<Type>().accept1( node->type );
    170                 auto attr = get<Attribute>().acceptL( node->attributes );
    171 
    172164                auto decl = new ObjectDecl(
    173165                        node->name,
     
    176168                        bfwd,
    177169                        type->clone(),
    178                         nullptr, // prevent infinite loop
     170                        init,
    179171                        attr,
    180172                        Type::FuncSpecifiers( node->funcSpec.val )
    181173                );
    182 
    183                 // handles the case where node->init references itself
    184                 // xxx - does it really happen?
    185                 declWithTypePostamble(decl, node);
    186                 auto init = get<Initializer>().accept1( node->init );
    187                 decl->init = init;
    188                
    189                 this->node = decl;
    190                 return nullptr;
     174                return declWithTypePostamble( decl, node );
    191175        }
    192176
     
    221205                decl->statements = get<CompoundStmt>().accept1( node->stmts );
    222206                decl->withExprs = get<Expression>().acceptL( node->withExprs );
    223                 if ( ast::dereferenceOperator == node ) {
     207                if ( dereferenceOperator == node ) {
    224208                        Validate::dereferenceOperator = decl;
    225209                }
    226                 if ( ast::dtorStructDestroy == node ) {
     210                if ( dtorStructDestroy == node ) {
    227211                        Validate::dtorStructDestroy = decl;
    228212                }
     
    283267                );
    284268
    285                 if ( ast::dtorStruct == node ) {
     269                if ( dtorStruct == node ) {
    286270                        Validate::dtorStruct = decl;
    287271                }
     
    336320
    337321        const ast::Stmt * stmtPostamble( Statement * stmt, const ast::Stmt * node ) {
    338                 // force statements in old tree to be unique.
    339                 // cache.emplace( node, stmt );
    340                 readonlyCache.emplace( node, stmt );
     322                cache.emplace( node, stmt );
    341323                stmt->location = node->location;
    342324                stmt->labels = makeLabelL( stmt, node->labels );
     
    355337                if ( inCache( node ) ) return nullptr;
    356338                auto stmt = new ExprStmt( nullptr );
     339                cache.emplace( node, stmt );
    357340                stmt->expr = get<Expression>().accept1( node->expr );
    358341                return stmtPostamble( stmt, node );
     
    10281011                auto stmts = node->stmts;
    10291012                // disable sharing between multiple StmtExprs explicitly.
    1030                 // this should no longer be true.
    1031 
     1013                if (inCache(stmts)) {
     1014                        stmts = ast::deepCopy(stmts.get());
     1015                }
    10321016                auto rslt = new StmtExpr(
    10331017                        get<CompoundStmt>().accept1(stmts)
     
    10361020                rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
    10371021                rslt->dtors       = get<Expression>().acceptL(node->dtors);
    1038                 if (node->resultExpr) {
    1039                         // this MUST be found by children visit
    1040                         rslt->resultExpr  = strict_dynamic_cast<ExprStmt *>(readonlyCache.at(node->resultExpr));
    1041                 }
    10421022
    10431023                auto expr = visitBaseExpr( node, rslt );
     
    10561036
    10571037                auto expr = visitBaseExpr( node, rslt );
    1058                 this->node = expr->clone();
     1038                this->node = expr;
    10591039                return nullptr;
    10601040        }
     
    11461126                auto type = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind };
    11471127                // I believe this should always be a BasicType.
    1148                 if ( ast::sizeType == node ) {
     1128                if ( sizeType == node ) {
    11491129                        Validate::SizeType = type;
    11501130                }
     
    15491529
    15501530                // function type is now derived from parameter decls instead of storing them
    1551 
    1552                 /*
    15531531                auto ftype = new ast::FunctionType((ast::ArgumentFlag)old->type->isVarArgs, cv(old->type));
    15541532                ftype->params.reserve(paramVars.size());
     
    15621540                }
    15631541                ftype->forall = std::move(forall);
    1564                 */
    1565 
    1566                 // can function type have attributes? seems not to be the case.
    1567                 // visitType(old->type, ftype);
     1542                visitType(old->type, ftype);
    15681543
    15691544                auto decl = new ast::FunctionDecl{
     
    15711546                        old->name,
    15721547                        // GET_ACCEPT_1(type, FunctionType),
    1573                         std::move(forall),
    15741548                        std::move(paramVars),
    15751549                        std::move(returnVars),
     
    15781552                        { old->linkage.val },
    15791553                        GET_ACCEPT_V(attributes, Attribute),
    1580                         { old->get_funcSpec().val },
    1581                         old->type->isVarArgs
     1554                        { old->get_funcSpec().val }
    15821555                };
    15831556
    1584                 // decl->type = ftype;
     1557                decl->type = ftype;
    15851558                cache.emplace( old, decl );
    15861559
     
    15971570
    15981571                if ( Validate::dereferenceOperator == old ) {
    1599                         ast::dereferenceOperator = decl;
     1572                        dereferenceOperator = decl;
    16001573                }
    16011574
    16021575                if ( Validate::dtorStructDestroy == old ) {
    1603                         ast::dtorStructDestroy = decl;
     1576                        dtorStructDestroy = decl;
    16041577                }
    16051578        }
     
    16261599
    16271600                if ( Validate::dtorStruct == old ) {
    1628                         ast::dtorStruct = decl;
     1601                        dtorStruct = decl;
    16291602                }
    16301603        }
     
    25582531                // I believe this should always be a BasicType.
    25592532                if ( Validate::SizeType == old ) {
    2560                         ast::sizeType = type;
     2533                        sizeType = type;
    25612534                }
    25622535                visitType( old, type );
  • src/AST/Decl.cpp

    rf7e4f8e8 rb9537e6  
    4848
    4949// --- FunctionDecl
    50 
    51 FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name,
    52                 std::vector<ptr<TypeDecl>>&& forall,
    53                 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    54                 CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
    55                 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)
    56         : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
    57           stmts( stmts ) {
    58                   FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(isVarArgs));
    59                   for (auto & param : this->params) {
    60                           ftype->params.emplace_back(param->get_type());
    61                   }
    62                   for (auto & ret : this->returns) {
    63                           ftype->returns.emplace_back(ret->get_type());
    64                   }
    65                   ftype->forall = std::move(forall);
    66                   this->type = ftype;
    67           }
    68 
    6950
    7051const Type * FunctionDecl::get_type() const { return type.get(); }
  • src/AST/Decl.hpp

    rf7e4f8e8 rb9537e6  
    131131        std::vector< ptr<Expr> > withExprs;
    132132
    133         FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall,
     133        FunctionDecl( const CodeLocation & loc, const std::string & name,
    134134                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    135135                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
    136                 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);
    137         // : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
    138         //  stmts( stmts ) {}
     136                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {})
     137        : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
     138          stmts( stmts ) {}
    139139
    140140        const Type * get_type() const override;
  • src/AST/DeclReplacer.cpp

    rf7e4f8e8 rb9537e6  
    3838                        const ast::TypeInstType * previsit( const ast::TypeInstType * );
    3939                };
    40 
    41                 struct VarExprReplacer {
    42                 private:
    43                         const ExprMap & exprMap;
    44                        
    45                 public:
    46                         VarExprReplacer(const ExprMap & exprMap): exprMap (exprMap) {}
    47 
    48                         const Expr * postvisit (const VariableExpr *);
    49                 };
    5040        }
    5141
     
    6454                DeclMap declMap;
    6555                return replace( node, declMap, typeMap, debug );
    66         }
    67 
    68         const ast::Node * replace( const ast::Node * node, const ExprMap & exprMap) {
    69                 Pass<VarExprReplacer> replacer = {exprMap};
    70                 return node->accept( replacer );
    7156        }
    7257
     
    10388                        return ninst;
    10489                }
    105 
    106                 const Expr * VarExprReplacer::postvisit( const VariableExpr * expr ) {
    107                         if (!exprMap.count(expr->var)) return expr;
    108 
    109                         return exprMap.at(expr->var);
    110                 }
    111 
    11290        }
    11391}
  • src/AST/DeclReplacer.hpp

    rf7e4f8e8 rb9537e6  
    2323        class DeclWithType;
    2424        class TypeDecl;
    25         class Expr;
    2625
    2726        namespace DeclReplacer {
    2827                using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >;
    2928                using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >;
    30                 using ExprMap = std::unordered_map< const DeclWithType *, const Expr * >;
    3129
    3230                const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false );
    3331                const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false );
    3432                const Node * replace( const Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
    35                 const Node * replace( const Node * node, const ExprMap & exprMap);
    3633        }
    3734}
  • src/AST/Expr.cpp

    rf7e4f8e8 rb9537e6  
    6767// --- UntypedExpr
    6868
    69 UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, const Expr * arg ) {
     69UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, Expr * arg ) {
    7070        assert( arg );
    7171
     
    9292}
    9393
    94 UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs ) {
     94UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs ) {
    9595        assert( lhs && rhs );
    9696
     
    102102        }
    103103        return ret;
    104 }
    105 
    106 // --- VariableExpr
    107 
    108 VariableExpr::VariableExpr( const CodeLocation & loc )
    109 : Expr( loc ), var( nullptr ) {}
    110 
    111 VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
    112 : Expr( loc ), var( v ) {
    113         assert( var );
    114         assert( var->get_type() );
    115         result = shallowCopy( var->get_type() );
    116 }
    117 
    118 bool VariableExpr::get_lvalue() const {
    119         // It isn't always an lvalue, but it is never an rvalue.
    120         return true;
    121 }
    122 
    123 VariableExpr * VariableExpr::functionPointer(
    124                 const CodeLocation & loc, const FunctionDecl * decl ) {
    125         // wrap usually-determined result type in a pointer
    126         VariableExpr * funcExpr = new VariableExpr{ loc, decl };
    127         funcExpr->result = new PointerType{ funcExpr->result };
    128         return funcExpr;
    129104}
    130105
     
    263238}
    264239
     240// --- VariableExpr
     241
     242VariableExpr::VariableExpr( const CodeLocation & loc )
     243: Expr( loc ), var( nullptr ) {}
     244
     245VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
     246: Expr( loc ), var( v ) {
     247        assert( var );
     248        assert( var->get_type() );
     249        result = shallowCopy( var->get_type() );
     250}
     251
     252bool VariableExpr::get_lvalue() const {
     253        // It isn't always an lvalue, but it is never an rvalue.
     254        return true;
     255}
     256
     257VariableExpr * VariableExpr::functionPointer(
     258                const CodeLocation & loc, const FunctionDecl * decl ) {
     259        // wrap usually-determined result type in a pointer
     260        VariableExpr * funcExpr = new VariableExpr{ loc, decl };
     261        funcExpr->result = new PointerType{ funcExpr->result };
     262        return funcExpr;
     263}
     264
    265265// --- ConstantExpr
    266266
  • src/AST/Expr.hpp

    rf7e4f8e8 rb9537e6  
    226226
    227227        /// Creates a new dereference expression
    228         static UntypedExpr * createDeref( const CodeLocation & loc, const Expr * arg );
     228        static UntypedExpr * createDeref( const CodeLocation & loc, Expr * arg );
    229229        /// Creates a new assignment expression
    230         static UntypedExpr * createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs );
     230        static UntypedExpr * createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs );
    231231
    232232        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    247247private:
    248248        NameExpr * clone() const override { return new NameExpr{ *this }; }
    249         MUTATE_FRIEND
    250 };
    251 
    252 /// A reference to a named variable.
    253 class VariableExpr final : public Expr {
    254 public:
    255         readonly<DeclWithType> var;
    256 
    257         VariableExpr( const CodeLocation & loc );
    258         VariableExpr( const CodeLocation & loc, const DeclWithType * v );
    259 
    260         bool get_lvalue() const final;
    261 
    262         /// generates a function pointer for a given function
    263         static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
    264 
    265         const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    266 private:
    267         VariableExpr * clone() const override { return new VariableExpr{ *this }; }
    268249        MUTATE_FRIEND
    269250};
     
    411392};
    412393
     394/// A reference to a named variable.
     395class VariableExpr final : public Expr {
     396public:
     397        readonly<DeclWithType> var;
     398
     399        VariableExpr( const CodeLocation & loc );
     400        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
     401
     402        bool get_lvalue() const final;
     403
     404        /// generates a function pointer for a given function
     405        static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
     406
     407        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     408private:
     409        VariableExpr * clone() const override { return new VariableExpr{ *this }; }
     410        MUTATE_FRIEND
     411};
     412
    413413/// A compile-time constant.
    414414/// Mostly carries C-source text from parse to code-gen, without interpretation.  E.g. strings keep their outer quotes and never have backslashes interpreted.
     
    422422                const CodeLocation & loc, const Type * ty, const std::string & r,
    423423                        std::optional<unsigned long long> i )
    424         : Expr( loc, ty ), rep( r ), ival( i ), underlyer(ty) {}
     424        : Expr( loc, ty ), rep( r ), ival( i ) {}
    425425
    426426        /// Gets the integer value of this constant, if one is appropriate to its type.
     
    617617
    618618        ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call )
    619         : Expr( loc, call->result ), callExpr(call) { assert( call ); assert(call->result); }
     619        : Expr( loc, call->result ) { assert( call ); }
    620620
    621621        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    742742        std::vector<ptr<Expr>> dtors;              ///< destructor(s) for return variable(s)
    743743
    744         readonly<ExprStmt> resultExpr;
    745 
    746744        StmtExpr( const CodeLocation & loc, const CompoundStmt * ss );
    747745
  • src/AST/Fwd.hpp

    rf7e4f8e8 rb9537e6  
    137137typedef unsigned int UniqueId;
    138138
    139 extern Type * sizeType;
    140 extern FunctionDecl * dereferenceOperator;
    141 extern StructDecl   * dtorStruct;
    142 extern FunctionDecl * dtorStructDestroy;
    143 
    144139}
  • src/AST/Node.hpp

    rf7e4f8e8 rb9537e6  
    4949
    5050        bool unique() const { return strong_count == 1; }
    51         bool isManaged() const {return strong_count > 0; }
    5251
    5352private:
  • src/AST/Pass.hpp

    rf7e4f8e8 rb9537e6  
    228228        template<typename core_type>
    229229        friend void accept_all( std::list< ptr<Decl> > & decls, Pass<core_type>& visitor );
    230 
    231         bool isInFunction() const {
    232                 return inFunction;
    233         }
    234 
    235230private:
    236231
     
    240235        const ast::Stmt * call_accept( const ast::Stmt * );
    241236        const ast::Expr * call_accept( const ast::Expr * );
    242 
    243         // requests WithStmtsToAdd directly add to this statement, as if it is a compound.
    244 
    245         const ast::Stmt * call_accept_as_compound(const ast::Stmt *);
    246237
    247238        template< typename node_t >
     
    266257        template<typename node_t, typename parent_t, typename child_t>
    267258        void maybe_accept(const node_t * &, child_t parent_t::* child);
    268 
    269         template<typename node_t, typename parent_t, typename child_t>
    270         void maybe_accept_as_compound(const node_t * &, child_t parent_t::* child);
    271259
    272260private:
     
    296284private:
    297285        bool inFunction = false;
    298         bool atFunctionTop = false;
    299286};
    300287
     
    384371struct WithVisitorRef {
    385372        Pass<core_t> * const visitor = nullptr;
    386 
    387         bool isInFunction() const {
    388                 return visitor->isInFunction();
    389         }
    390373};
    391374
  • src/AST/Pass.impl.hpp

    rf7e4f8e8 rb9537e6  
    167167                __pedantic_pass_assert( stmt );
    168168
    169                 return stmt->accept( *this );
    170         }
    171 
    172         template< typename core_t >
    173         const ast::Stmt * ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
    174                 __pedantic_pass_assert( __visit_children() );
    175                 __pedantic_pass_assert( stmt );
    176 
    177169                // add a few useful symbols to the scope
    178170                using __pass::empty;
     
    332324
    333325                auto new_val = call_accept( old_val );
    334 
    335                 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
    336 
    337                 if( __pass::differs(old_val, new_val) ) {
    338                         auto new_parent = __pass::mutate<core_t>(parent);
    339                         new_parent->*child = new_val;
    340                         parent = new_parent;
    341                 }
    342         }
    343 
    344         template< typename core_t >
    345         template<typename node_t, typename parent_t, typename child_t>
    346         void ast::Pass< core_t >::maybe_accept_as_compound(
    347                 const node_t * & parent,
    348                 child_t parent_t::*child
    349         ) {
    350                 static_assert( std::is_base_of<parent_t, node_t>::value, "Error deducing member object" );
    351 
    352                 if(__pass::skip(parent->*child)) return;
    353                 const auto & old_val = __pass::get(parent->*child, 0);
    354 
    355                 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
    356 
    357                 auto new_val = call_accept_as_compound( old_val );
    358326
    359327                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
     
    502470                                // foralls are still in function type
    503471                                maybe_accept( node, &FunctionDecl::type );
    504                                 // First remember that we are now within a function.
     472                                // function body needs to have the same scope as parameters - CompoundStmt will not enter
     473                                // a new scope if inFunction is true
    505474                                ValueGuard< bool > oldInFunction( inFunction );
    506475                                inFunction = true;
    507                                 // The function body needs to have the same scope as parameters.
    508                                 // A CompoundStmt will not enter a new scope if atFunctionTop is true.
    509                                 ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
    510                                 atFunctionTop = true;
    511476                                maybe_accept( node, &FunctionDecl::stmts );
    512477                                maybe_accept( node, &FunctionDecl::attributes );
     
    675640        VISIT_START( node );
    676641        VISIT({
    677                 // Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result.
    678                 auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() {
    679                         if ( enterScope ) __pass::symtab::enter(core, 0);
    680                 }, [this, leaveScope = !this->atFunctionTop]() {
    681                         if ( leaveScope ) __pass::symtab::leave(core, 0);
     642                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
     643                auto guard1 = makeFuncGuard( [this, inFunctionCpy = this->inFunction]() {
     644                        if ( ! inFunctionCpy ) __pass::symtab::enter(core, 0);
     645                }, [this, inFunctionCpy = this->inFunction]() {
     646                        if ( ! inFunctionCpy ) __pass::symtab::leave(core, 0);
    682647                });
    683648                ValueGuard< bool > guard2( inFunction );
     
    738703                maybe_accept( node, &IfStmt::inits    );
    739704                maybe_accept( node, &IfStmt::cond     );
    740                 maybe_accept_as_compound( node, &IfStmt::thenPart );
    741                 maybe_accept_as_compound( node, &IfStmt::elsePart );
     705                maybe_accept( node, &IfStmt::thenPart );
     706                maybe_accept( node, &IfStmt::elsePart );
    742707        })
    743708
     
    756721                maybe_accept( node, &WhileStmt::inits );
    757722                maybe_accept( node, &WhileStmt::cond  );
    758                 maybe_accept_as_compound( node, &WhileStmt::body  );
     723                maybe_accept( node, &WhileStmt::body  );
    759724        })
    760725
     
    771736                // for statements introduce a level of scope (for the initialization)
    772737                guard_symtab guard { *this };
    773                 // xxx - old ast does not create WithStmtsToAdd scope for loop inits. should revisit this later.
    774738                maybe_accept( node, &ForStmt::inits );
    775739                maybe_accept( node, &ForStmt::cond  );
    776740                maybe_accept( node, &ForStmt::inc   );
    777                 maybe_accept_as_compound( node, &ForStmt::body  );
     741                maybe_accept( node, &ForStmt::body  );
    778742        })
    779743
     
    870834                maybe_accept( node, &CatchStmt::decl );
    871835                maybe_accept( node, &CatchStmt::cond );
    872                 maybe_accept_as_compound( node, &CatchStmt::body );
     836                maybe_accept( node, &CatchStmt::body );
    873837        })
    874838
  • src/AST/SymbolTable.cpp

    rf7e4f8e8 rb9537e6  
    335335}
    336336
    337 
    338 void SymbolTable::addFunction( const FunctionDecl * func ) {
    339         addTypes( func->type->forall );
    340         addIds( func->returns );
    341         addIds( func->params );
    342 }
    343 
     337/*
     338void SymbolTable::addFunctionType( const FunctionType * ftype ) {
     339        addTypes( ftype->forall );
     340        addIds( ftype->returns );
     341        addIds( ftype->params );
     342}
     343*/
    344344
    345345void SymbolTable::lazyInitScope() {
  • src/AST/SymbolTable.hpp

    rf7e4f8e8 rb9537e6  
    145145
    146146        /// convenience function for adding all of the declarations in a function type to the indexer
    147         void addFunction( const FunctionDecl * );
     147        // void addFunctionType( const FunctionType * ftype );
    148148
    149149private:
  • src/AST/Type.cpp

    rf7e4f8e8 rb9537e6  
    157157
    158158template<typename decl_t>
    159 SueInstType<decl_t>::SueInstType(
    160         const base_type * b, std::vector<ptr<Expr>> && params,
    161         CV::Qualifiers q, std::vector<ptr<Attribute>> && as )
    162 : BaseInstType( b->name, std::move(params), q, std::move(as) ), base( b ) {}
    163 
    164 template<typename decl_t>
    165159bool SueInstType<decl_t>::isComplete() const {
    166160        return base ? base->body : false;
  • src/AST/Type.hpp

    rf7e4f8e8 rb9537e6  
    302302class FunctionType final : public ParameterizedType {
    303303public:
     304//      std::vector<ptr<DeclWithType>> returns;
     305//      std::vector<ptr<DeclWithType>> params;
     306
    304307        std::vector<ptr<Type>> returns;
    305308        std::vector<ptr<Type>> params;
     
    342345        : ParameterizedType(q, std::move(as)), params(), name(n) {}
    343346
    344         BaseInstType(
    345                 const std::string& n, std::vector<ptr<Expr>> && params,
    346                 CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    347         : ParameterizedType(q, std::move(as)), params(std::move(params)), name(n) {}
    348 
    349347        BaseInstType( const BaseInstType & o );
    350348
     
    371369
    372370        SueInstType(
    373                 const base_type * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    374 
    375         SueInstType(
    376                 const base_type * b, std::vector<ptr<Expr>> && params,
    377                 CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     371                const decl_t * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    378372
    379373        bool isComplete() const override;
  • src/AST/porting.md

    rf7e4f8e8 rb9537e6  
    3030  * Base nodes now override `const Node * accept( Visitor & v ) const = 0` with, e.g. `const Stmt * accept( Visitor & v ) const override = 0`
    3131* `PassVisitor` is replaced with `ast::Pass`
    32   * Most one shot uses can use `ast::Pass::run` and `ast::Pass::read`.
    33 
    34 `WithConstTypeSubstitution`
    35 * `env` => `typeSubs`
    3632
    3733## Structural Changes ##
     
    150146  * allows `newObject` as just default settings
    151147
    152 `FunctionDecl`
    153 * `params` and `returns` added.
    154   * Contain the declarations of the parameters and return variables.
    155   * Types should match (even be shared with) the fields of `type`.
    156 
    157148`NamedTypeDecl`
    158149* `parameters` => `params`
     
    163154`AggregateDecl`
    164155* `parameters` => `params`
    165 
    166 `StructDecl`
    167 * `makeInst` replaced by better constructor on `StructInstType`.
    168156
    169157`Expr`
     
    257245* **TODO** move `kind`, `typeNames` into code generator
    258246
    259 `ReferenceToType` => `BaseInstType`
     247`ReferenceToType`
    260248* deleted `get_baseParameters()` from children
    261249  * replace with `aggr() ? aggr()->params : nullptr`
     
    273261* `returnVals` => `returns`
    274262* `parameters` => `params`
    275   * Both now just point at types.
    276263* `bool isVarArgs;` => `enum ArgumentFlag { FixedArgs, VariableArgs }; ArgumentFlag isVarArgs;`
    277 
    278 `SueInstType`
    279 * Template class, with specializations and using to implement some other types:
    280   * `StructInstType`, `UnionInstType` & `EnumInstType`
    281264
    282265`TypeInstType`
  • src/Common/PassVisitor.h

    rf7e4f8e8 rb9537e6  
    354354        virtual TypeSubstitution * mutate( TypeSubstitution * sub ) final;
    355355
    356         bool isInFunction() const {
    357                 return inFunction;
    358         }
    359 
    360356private:
    361357        bool inFunction = false;
    362         bool atFunctionTop = false;
    363358
    364359        template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
     
    531526public:
    532527        PassVisitor<pass_type> * const visitor = nullptr;
    533 
    534         bool isInFunction() const {
    535                 return visitor->isInFunction();
    536         }
    537528};
    538529
  • src/Common/PassVisitor.impl.h

    rf7e4f8e8 rb9537e6  
    532532                        indexerAddId( &func );
    533533                        maybeAccept_impl( node->type, *this );
    534                         // First remember that we are now within a function.
     534                        // function body needs to have the same scope as parameters - CompoundStmt will not enter
     535                        // a new scope if inFunction is true
    535536                        ValueGuard< bool > oldInFunction( inFunction );
    536537                        inFunction = true;
    537                         // The function body needs to have the same scope as parameters.
    538                         // A CompoundStmt will not enter a new scope if atFunctionTop is true.
    539                         ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
    540                         atFunctionTop = true;
    541538                        maybeAccept_impl( node->statements, *this );
    542539                        maybeAccept_impl( node->attributes, *this );
     
    570567                        indexerAddId( &func );
    571568                        maybeAccept_impl( node->type, *this );
    572                         // First remember that we are now within a function.
     569                        // function body needs to have the same scope as parameters - CompoundStmt will not enter
     570                        // a new scope if inFunction is true
    573571                        ValueGuard< bool > oldInFunction( inFunction );
    574572                        inFunction = true;
    575                         // The function body needs to have the same scope as parameters.
    576                         // A CompoundStmt will not enter a new scope if atFunctionTop is true.
    577                         ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
    578                         atFunctionTop = true;
    579573                        maybeAccept_impl( node->statements, *this );
    580574                        maybeAccept_impl( node->attributes, *this );
     
    607601                        indexerAddId( &func );
    608602                        maybeMutate_impl( node->type, *this );
    609                         // First remember that we are now within a function.
     603                        // function body needs to have the same scope as parameters - CompoundStmt will not enter
     604                        // a new scope if inFunction is true
    610605                        ValueGuard< bool > oldInFunction( inFunction );
    611606                        inFunction = true;
    612                         // The function body needs to have the same scope as parameters.
    613                         // A CompoundStmt will not enter a new scope if atFunctionTop is true.
    614                         ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
    615                         atFunctionTop = true;
    616607                        maybeMutate_impl( node->statements, *this );
    617608                        maybeMutate_impl( node->attributes, *this );
     
    10161007        VISIT_START( node );
    10171008        {
    1018                 // Do not enter a new scope if atFunctionTop is true, don't leave one either.
    1019                 ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
    1020                 auto guard1 = makeFuncGuard( [this, go = !atFunctionTop]() { if ( go ) indexerScopeEnter(); }, [this, go = !atFunctionTop]() { if ( go ) indexerScopeLeave(); } );
     1009                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
     1010                ValueGuard< bool > oldInFunction( inFunction );
     1011                auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
    10211012                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
    1022                 atFunctionTop = false;
     1013                inFunction = false;
    10231014                visitStatementList( node->kids );
    10241015        }
     
    10301021        VISIT_START( node );
    10311022        {
    1032                 // Do not enter a new scope if atFunctionTop is true, don't leave one either.
    1033                 ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
    1034                 auto guard1 = makeFuncGuard( [this, go = !atFunctionTop]() { if ( go ) indexerScopeEnter(); }, [this, go = !atFunctionTop]() { if ( go ) indexerScopeLeave(); } );
     1023                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
     1024                ValueGuard< bool > oldInFunction( inFunction );
     1025                auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
    10351026                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
    1036                 atFunctionTop = false;
     1027                inFunction = false;
    10371028                visitStatementList( node->kids );
    10381029        }
     
    10441035        MUTATE_START( node );
    10451036        {
    1046                 // Do not enter a new scope if atFunctionTop is true, don't leave one either.
    1047                 ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
    1048                 auto guard1 = makeFuncGuard( [this, go = !atFunctionTop]() { if ( go ) indexerScopeEnter(); }, [this, go = !atFunctionTop]() { if ( go ) indexerScopeLeave(); } );
     1037                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
     1038                ValueGuard< bool > oldInFunction( inFunction );
     1039                auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
    10491040                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
    1050                 atFunctionTop = false;
     1041                inFunction = false;
    10511042                mutateStatementList( node->kids );
    10521043        }
  • src/Common/utility.h

    rf7e4f8e8 rb9537e6  
    360360        reverse_iterate_t( T & ref ) : ref(ref) {}
    361361
    362         // this does NOT work on const T!!!
    363         // typedef typename T::reverse_iterator iterator;
    364         auto begin() { return ref.rbegin(); }
    365         auto end() { return ref.rend(); }
     362        typedef typename T::reverse_iterator iterator;
     363        iterator begin() { return ref.rbegin(); }
     364        iterator end() { return ref.rend(); }
    366365};
    367366
  • src/Concurrency/Keywords.cc

    rf7e4f8e8 rb9537e6  
    4646        }
    4747
    48         // Only detects threads constructed with the keyword thread.
    49         inline static bool isThread( DeclarationWithType * decl ) {
    50                 Type * baseType = decl->get_type()->stripDeclarator();
    51                 StructInstType * instType = dynamic_cast<StructInstType *>( baseType );
    52                 if ( nullptr == instType ) { return false; }
    53                 return instType->baseStruct->is_thread();
    54         }
    55 
    5648        //=============================================================================================
    5749        // Pass declarations
     
    127119                        "get_thread",
    128120                        "thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
    129                         "ThreadCancelled",
     121                        "",
    130122                        true,
    131123                        AggregateDecl::Thread
     
    298290                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first );
    299291                void validate( DeclarationWithType * );
    300                 void addDtorStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    301                 void addStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    302                 void addThreadDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args );
     292                void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     293                void addStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    303294
    304295                static void implement( std::list< Declaration * > & translationUnit ) {
     
    311302                StructDecl* guard_decl = nullptr;
    312303                StructDecl* dtor_guard_decl = nullptr;
    313                 StructDecl* thread_guard_decl = nullptr;
    314304
    315305                static std::unique_ptr< Type > generic_func;
     
    811801                bool first = false;
    812802                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first );
    813                 bool const isDtor = CodeGen::isDestructor( decl->name );
     803                bool isDtor = CodeGen::isDestructor( decl->name );
    814804
    815805                // Is this function relevant to monitors
     
    859849
    860850                // Instrument the body
    861                 if ( isDtor && isThread( mutexArgs.front() ) ) {
    862                         if( !thread_guard_decl ) {
    863                                 SemanticError( decl, "thread destructor requires threads to be in scope, add #include <thread.hfa>\n" );
    864                         }
    865                         addThreadDtorStatements( decl, body, mutexArgs );
    866                 }
    867                 else if ( isDtor ) {
    868                         addDtorStatements( decl, body, mutexArgs );
     851                if( isDtor ) {
     852                        addDtorStatments( decl, body, mutexArgs );
    869853                }
    870854                else {
    871                         addStatements( decl, body, mutexArgs );
     855                        addStatments( decl, body, mutexArgs );
    872856                }
    873857        }
     
    886870                        assert( !dtor_guard_decl );
    887871                        dtor_guard_decl = decl;
    888                 }
    889                 else if( decl->name == "thread_dtor_guard_t" && decl->body ) {
    890                         assert( !thread_guard_decl );
    891                         thread_guard_decl = decl;
    892872                }
    893873        }
     
    928908        }
    929909
    930         void MutexKeyword::addDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
     910        void MutexKeyword::addDtorStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
    931911                Type * arg_type = args.front()->get_type()->clone();
    932912                arg_type->set_mutex( false );
     
    977957
    978958                //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
    979                 body->push_front( new DeclStmt( monitors ) );
    980         }
    981 
    982         void MutexKeyword::addThreadDtorStatements(
    983                         FunctionDecl*, CompoundStmt * body,
    984                         const std::list<DeclarationWithType * > & args ) {
    985                 assert( args.size() == 1 );
    986                 DeclarationWithType * arg = args.front();
    987                 Type * arg_type = arg->get_type()->clone();
    988                 assert( arg_type->get_mutex() );
    989                 arg_type->set_mutex( false );
    990 
    991                 // thread_dtor_guard_t __guard = { this, intptr( 0 ) };
    992                 body->push_front(
    993                         new DeclStmt( new ObjectDecl(
    994                                 "__guard",
    995                                 noStorageClasses,
    996                                 LinkageSpec::Cforall,
    997                                 nullptr,
    998                                 new StructInstType(
    999                                         noQualifiers,
    1000                                         thread_guard_decl
    1001                                 ),
    1002                                 new ListInit(
    1003                                         {
    1004                                                 new SingleInit( new CastExpr( new VariableExpr( arg ), arg_type ) ),
    1005                                                 new SingleInit( new UntypedExpr(
    1006                                                         new NameExpr( "intptr" ), {
    1007                                                                 new ConstantExpr( Constant::from_int( 0 ) ),
    1008                                                         }
    1009                                                 ) ),
    1010                                         },
    1011                                         noDesignators,
    1012                                         true
    1013                                 )
    1014                         ))
    1015                 );
    1016         }
    1017 
    1018         void MutexKeyword::addStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
     959                body->push_front( new DeclStmt( monitors) );
     960        }
     961
     962        void MutexKeyword::addStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
    1019963                ObjectDecl * monitors = new ObjectDecl(
    1020964                        "__monitors",
  • src/GenPoly/GenPoly.cc

    rf7e4f8e8 rb9537e6  
    4646                }
    4747
    48                 bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const ast::TypeSubstitution * env) {
    49                         for (auto &param : params) {
    50                                 auto paramType = param.strict_as<ast::TypeExpr>();
    51                                 if (isPolyType(paramType->type, env)) return true;
    52                         }
    53                         return false;
    54                 }
    55 
    5648                /// Checks a parameter list for polymorphic parameters from tyVars; will substitute according to env if present
    5749                bool hasPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
     
    6456                }
    6557
    66                 bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const TyVarMap & tyVars, const ast::TypeSubstitution * env) {
    67                         for (auto &param : params) {
    68                                 auto paramType = param.strict_as<ast::TypeExpr>();
    69                                 if (isPolyType(paramType->type, tyVars, env)) return true;
    70                         }
    71                         return false;
    72                 }
    73 
    7458                /// Checks a parameter list for dynamic-layout parameters from tyVars; will substitute according to env if present
    7559                bool hasDynParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
     
    10892                        Type *newType = env->lookup( typeInst->get_name() );
    10993                        if ( newType ) return newType;
    110                 }
    111                 return type;
    112         }
    113 
    114         const ast::Type * replaceTypeInst(const ast::Type * type, const ast::TypeSubstitution * env) {
    115                 if (!env) return type;
    116                 if (auto typeInst = dynamic_cast<const ast::TypeInstType*> (type)) {
    117                         auto newType = env->lookup(typeInst->name);
    118                         if (newType) return newType;
    11994                }
    12095                return type;
     
    136111        }
    137112
    138         const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env) {
    139                 type = replaceTypeInst( type, env );
    140 
    141                 if ( dynamic_cast< const ast::TypeInstType * >( type ) ) {
    142                         return type;
    143                 } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
    144                         return isPolyType( arrayType->base, env );
    145                 } else if ( auto structType = dynamic_cast< const ast::StructInstType* >( type ) ) {
    146                         if ( hasPolyParams( structType->params, env ) ) return type;
    147                 } else if ( auto unionType = dynamic_cast< const ast::UnionInstType* >( type ) ) {
    148                         if ( hasPolyParams( unionType->params, env ) ) return type;
    149                 }
    150                 return 0;
    151         }
    152 
    153113        Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
    154114                type = replaceTypeInst( type, env );
     
    166126                }
    167127                return 0;
    168         }
    169 
    170         const ast::Type * isPolyType(const ast::Type * type, const TyVarMap & tyVars, const ast::TypeSubstitution * env) {
    171                 type = replaceTypeInst( type, env );
    172 
    173                 if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    174                         return tyVars.find(typeInst->name) != tyVars.end() ? type : nullptr;
    175                 } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
    176                         return isPolyType( arrayType->base, env );
    177                 } else if ( auto structType = dynamic_cast< const ast::StructInstType* >( type ) ) {
    178                         if ( hasPolyParams( structType->params, env ) ) return type;
    179                 } else if ( auto unionType = dynamic_cast< const ast::UnionInstType* >( type ) ) {
    180                         if ( hasPolyParams( unionType->params, env ) ) return type;
    181                 }
    182                 return nullptr;
    183128        }
    184129
     
    504449        }
    505450
    506         namespace {
    507                 // temporary hack to avoid re-implementing anything related to TyVarMap
    508                 // does this work? these two structs have identical definitions.
    509                 inline TypeDecl::Data convData(const ast::TypeDecl::Data & data) {
    510                         return *reinterpret_cast<const TypeDecl::Data *>(&data);
    511                 }
    512         }
    513 
    514451        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) {
    515452                // is parameter is not polymorphic, don't need to box
     
    522459        }
    523460
    524         bool needsBoxing( const ast::Type * param, const ast::Type * arg, const TyVarMap &exprTyVars, const ast::TypeSubstitution * env) {
    525                 // is parameter is not polymorphic, don't need to box
    526                 if ( ! isPolyType( param, exprTyVars ) ) return false;
    527                 ast::ptr<ast::Type> newType = arg;
    528                 if ( env ) env->apply( newType );
    529                 // if the argument's type is polymorphic, we don't need to box again!
    530                 return ! isPolyType( newType );
    531         }
    532 
    533461        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) {
    534462                FunctionType * function = getFunctionType( appExpr->function->result );
     
    539467        }
    540468
    541         bool needsBoxing( const ast::Type * param, const ast::Type * arg, const ast::ApplicationExpr * appExpr, const ast::TypeSubstitution * env) {
    542                 const ast::FunctionType * function = getFunctionType(appExpr->func->result);
    543                 assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->func->result ).c_str() );
    544                 TyVarMap exprTyVars(TypeDecl::Data{});
    545                 makeTyVarMap(function, exprTyVars);
    546                 return needsBoxing(param, arg, exprTyVars, env);
    547 
    548         }
    549 
    550469        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
    551470                tyVarMap.insert( tyVar->name, TypeDecl::Data{ tyVar } );
    552         }
    553 
    554         void addToTyVarMap( const ast::TypeDecl * tyVar, TyVarMap & tyVarMap) {
    555                 tyVarMap.insert(tyVar->name, convData(ast::TypeDecl::Data{tyVar}));
    556471        }
    557472
     
    563478                if ( PointerType *pointer = dynamic_cast< PointerType* >( type ) ) {
    564479                        makeTyVarMap( pointer->get_base(), tyVarMap );
    565                 }
    566         }
    567 
    568         void makeTyVarMap(const ast::Type * type, TyVarMap & tyVarMap) {
    569                 if (auto ptype = dynamic_cast<const ast::ParameterizedType *>(type)) {
    570                         for (auto & tyVar : ptype->forall) {
    571                                 assert (tyVar);
    572                                 addToTyVarMap(tyVar, tyVarMap);
    573                         }
    574                 }
    575                 if (auto pointer = dynamic_cast<const ast::PointerType *>(type)) {
    576                         makeTyVarMap(pointer->base, tyVarMap);
    577480                }
    578481        }
  • src/GenPoly/GenPoly.h

    rf7e4f8e8 rb9537e6  
    2626
    2727namespace GenPoly {
     28        typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;
    2829
    29         typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;
    3030        /// Replaces a TypeInstType by its referrent in the environment, if applicable
    3131        Type* replaceTypeInst( Type* type, const TypeSubstitution* env );
     
    3333        /// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided
    3434        Type *isPolyType( Type *type, const TypeSubstitution *env = 0 );
    35         const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env = nullptr);
    3635
    3736        /// returns polymorphic type if is polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided
    3837        Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
    39         const ast::Type * isPolyType(const ast::Type * type, const TyVarMap & tyVars, const ast::TypeSubstitution * env = nullptr);
    4038
    4139        /// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided
     
    8684        /// true if arg requires boxing given exprTyVars
    8785        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env );
    88         bool needsBoxing( const ast::Type * param, const ast::Type * arg, const TyVarMap &exprTyVars, const ast::TypeSubstitution * env);
    8986
    9087        /// true if arg requires boxing in the call to appExpr
    9188        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env );
    92         bool needsBoxing( const ast::Type * param, const ast::Type * arg, const ast::ApplicationExpr * appExpr, const ast::TypeSubstitution * env);
    9389
    9490        /// Adds the type variable `tyVar` to `tyVarMap`
     
    9793        /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap`
    9894        void makeTyVarMap( Type *type, TyVarMap &tyVarMap );
    99         void makeTyVarMap(const ast::Type * type, TyVarMap & tyVarMap);
    10095
    10196        /// Prints type variable map
  • src/GenPoly/Specialize.cc

    rf7e4f8e8 rb9537e6  
    218218                thunkFunc->get_attributes().push_back( new Attribute( "unused" ) );
    219219
    220                 // Thunks at the global level must be static to avoid collisions between files.
    221                 // (Conversly thunks inside a function must be unique and not static.)
    222                 thunkFunc->storageClasses.is_static = !isInFunction();
    223 
    224220                // thread thunk parameters into call to actual function, naming thunk parameters as we go
    225221                UniqueName paramNamer( paramPrefix );
  • src/InitTweak/FixGlobalInit.cc

    rf7e4f8e8 rb9537e6  
    3434#include "SynTree/Visitor.h"       // for acceptAll, Visitor
    3535
    36 #include "AST/Expr.hpp"
    37 #include "AST/Node.hpp"
    38 #include "AST/Pass.hpp"
    39 
    4036namespace InitTweak {
    4137        class GlobalFixer : public WithShortCircuiting {
     
    5450                FunctionDecl * initFunction;
    5551                FunctionDecl * destroyFunction;
    56         };
    57 
    58         class GlobalFixer_new : public ast::WithShortCircuiting {
    59         public:
    60                 void previsit (const ast::ObjectDecl *);
    61                 void previsit (const ast::FunctionDecl *) { visit_children = false; }
    62                 void previsit (const ast::StructDecl *) { visit_children = false; }
    63                 void previsit (const ast::UnionDecl *) { visit_children = false; }
    64                 void previsit (const ast::EnumDecl *) { visit_children = false; }
    65                 void previsit (const ast::TraitDecl *) { visit_children = false; }
    66                 void previsit (const ast::TypeDecl *) { visit_children = false; }
    67 
    68                 std::list< ast::ptr<ast::Stmt> > initStmts;
    69                 std::list< ast::ptr<ast::Stmt> > destroyStmts;
    7052        };
    7153
     
    10991        }
    11092
    111         void fixGlobalInit(std::list<ast::ptr<ast::Decl>> & translationUnit, bool inLibrary) {
    112                 ast::Pass<GlobalFixer_new> fixer;
    113                 accept_all(translationUnit, fixer);
    114 
    115                 if ( !fixer.core.initStmts.empty() ) {
    116                         std::vector<ast::ptr<ast::Expr>> ctorParams;
    117                         if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int({}, 200));
    118                         auto initFunction = new ast::FunctionDecl({}, "__global_init__", {}, {}, {}, new ast::CompoundStmt({}, std::move(fixer.core.initStmts)),
    119                                 ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("constructor", std::move(ctorParams))});
    120 
    121                         translationUnit.emplace_back( initFunction );
    122                 } // if
    123 
    124                 if ( !fixer.core.destroyStmts.empty() ) {
    125                         std::vector<ast::ptr<ast::Expr>> dtorParams;
    126                         if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int({}, 200));
    127                         auto destroyFunction = new ast::FunctionDecl({}, "__global_destroy__", {}, {}, {}, new ast::CompoundStmt({}, std::move(fixer.core.destroyStmts)),
    128                                 ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("destructor", std::move(dtorParams))});
    129 
    130                         translationUnit.emplace_back(destroyFunction);
    131                 } // if
    132         }
    133 
    13493        void GlobalFixer::previsit( ObjectDecl *objDecl ) {
    13594                std::list< Statement * > & initStatements = initFunction->get_statements()->get_kids();
     
    153112                        } // if
    154113                        if ( Statement * ctor = ctorInit->ctor ) {
    155                                 addDataSectonAttribute( objDecl );
     114                                // Translation 1: Add this attribute on the global declaration:
     115                                //    __attribute__((section (".data#")))
     116                                // which makes gcc put the global in the data section,
     117                                // so that the global is writeable (via a const cast) in the init function.
     118                                // The trailing # is an injected assembly comment, to suppress the "a" in
     119                                //    .section .data,"a"
     120                                //    .section .data#,"a"
     121                                // to avoid assembler warning "ignoring changed section attributes for .data"
     122                                Type *strLitT = new PointerType( Type::Qualifiers( ),
     123                                        new BasicType( Type::Qualifiers( ), BasicType::Char ) );
     124                                std::list< Expression * > attr_params;
     125                                attr_params.push_back(
     126                                        new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) );
     127                                objDecl->attributes.push_back(new Attribute("section", attr_params));
     128                                // Translation 2: Move the initizliation off the global declaration,
     129                                // into the startup function.
    156130                                initStatements.push_back( ctor );
    157131                                objDecl->init = nullptr;
     
    165139                        } // if
    166140                        delete ctorInit;
    167                 } // if
    168         }
    169 
    170         void GlobalFixer_new::previsit(const ast::ObjectDecl * objDecl) {
    171                 auto mutDecl = mutate(objDecl);
    172                 assertf(mutDecl == objDecl, "Global object decl must be unique");
    173                 if ( auto ctorInit = objDecl->init.as<ast::ConstructorInit>() ) {
    174                         // a decision should have been made by the resolver, so ctor and init are not both non-NULL
    175                         assert( ! ctorInit->ctor || ! ctorInit->init );
    176 
    177                         const ast::Stmt * dtor = ctorInit->dtor;
    178                         if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    179                                 // don't need to call intrinsic dtor, because it does nothing, but
    180                                 // non-intrinsic dtors must be called
    181                                 destroyStmts.push_front( dtor );
    182                                 // ctorInit->dtor = nullptr;
    183                         } // if
    184                         if ( const ast::Stmt * ctor = ctorInit->ctor ) {
    185                                 initStmts.push_back( ctor );
    186                                 mutDecl->init = nullptr;
    187                                 // ctorInit->ctor = nullptr;
    188                         } else if ( const ast::Init * init = ctorInit->init ) {
    189                                 mutDecl->init = init;
    190                                 // ctorInit->init = nullptr;
    191                         } else {
    192                                 // no constructor and no initializer, which is okay
    193                                 mutDecl->init = nullptr;
    194                         } // if
    195                         // delete ctorInit;
    196141                } // if
    197142        }
  • src/InitTweak/FixGlobalInit.h

    rf7e4f8e8 rb9537e6  
    1919#include <string>  // for string
    2020
    21 #include <AST/Fwd.hpp>
    22 
    23 
    2421class Declaration;
    2522
     
    2926        /// function is for library code.
    3027        void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary );
    31         void fixGlobalInit( std::list< ast::ptr<ast::Decl> > & translationUnit, bool inLibrary );
    3228} // namespace
    3329
  • src/InitTweak/FixInit.cc

    rf7e4f8e8 rb9537e6  
    219219                };
    220220
    221                 struct SplitExpressions : public WithShortCircuiting, /*public WithTypeSubstitution, */public WithStmtsToAdd {
     221                struct SplitExpressions : public WithShortCircuiting, public WithTypeSubstitution, public WithStmtsToAdd {
    222222                        /// add CompoundStmts around top-level expressions so that temporaries are destroyed in the correct places.
    223223                        static void split( std::list< Declaration * > &translationUnit );
     
    802802                                if ( Statement * ctor = ctorInit->get_ctor() ) {
    803803                                        if ( objDecl->get_storageClasses().is_static ) {
    804 
    805                                                 // The ojbect needs to go in the data section, regardless of dtor complexity below.
    806                                                 // The attribute works, and is meant to apply, both for leaving the static local alone,
    807                                                 // and for hoisting it out as a static global.
    808                                                 addDataSectonAttribute( objDecl );
    809 
    810804                                                // originally wanted to take advantage of gcc nested functions, but
    811805                                                // we get memory errors with this approach. To remedy this, the static
  • src/InitTweak/FixInit.h

    rf7e4f8e8 rb9537e6  
    1919#include <string>  // for string
    2020
    21 #include <AST/Fwd.hpp>
    22 
    2321class Declaration;
    2422
     
    2624        /// replace constructor initializers with expression statements and unwrap basic C-style initializers
    2725        void fix( std::list< Declaration * > & translationUnit, bool inLibrary );
    28 
    29         void fix( std::list<ast::ptr<ast::Decl>> & translationUnit, bool inLibrary);
    3026} // namespace
    3127
  • src/InitTweak/GenInit.cc

    rf7e4f8e8 rb9537e6  
    283283                assert( stmts.size() <= 1 );
    284284                return stmts.size() == 1 ? strict_dynamic_cast< ImplicitCtorDtorStmt * >( stmts.front() ) : nullptr;
    285 
    286         }
    287 
    288         ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) {
    289                 assertf(objDecl, "genCtorDtor passed null objDecl");
    290                 InitExpander_new srcParam(arg);
    291                 return SymTab::genImplicitCall(srcParam, new ast::VariableExpr(loc, objDecl), loc, fname, objDecl);
    292285        }
    293286
  • src/InitTweak/GenInit.h

    rf7e4f8e8 rb9537e6  
    3333        /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
    3434        ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr );
    35         ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg = nullptr);
    3635
    3736        /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
  • src/InitTweak/InitTweak.cc

    rf7e4f8e8 rb9537e6  
    498498        }
    499499
    500         const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func) {
    501                 assertf( func, "getParamThis: nullptr ftype" );
    502                 auto & params = func->params;
    503                 assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( func ).c_str());
    504                 return params.front().strict_as<ast::ObjectDecl>();
    505         }
    506 
    507500        bool tryConstruct( DeclarationWithType * dwt ) {
    508501                ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt );
     
    518511        }
    519512
    520         bool tryConstruct( const ast::DeclWithType * dwt ) {
    521                 auto objDecl = dynamic_cast< const ast::ObjectDecl * >( dwt );
    522                 if ( ! objDecl ) return false;
    523                 return (objDecl->init == nullptr ||
    524                                 ( objDecl->init != nullptr && objDecl->init->maybeConstructed ))
    525                         && ! objDecl->storage.is_extern
    526                         && isConstructable( objDecl->type );
    527         }
    528 
    529         bool isConstructable( const ast::Type * type ) {
    530                 return ! dynamic_cast< const ast::VarArgsType * >( type ) && ! dynamic_cast< const ast::ReferenceType * >( type )
    531                 && ! dynamic_cast< const ast::FunctionType * >( type ) && ! Tuples::isTtype( type );
    532         }
    533 
    534513        struct CallFinder_old {
    535514                CallFinder_old( const std::list< std::string > & names ) : names( names ) {}
     
    557536
    558537        struct CallFinder_new final {
    559                 std::vector< const ast::Expr * > matches;
     538                std::vector< ast::ptr< ast::Expr > > matches;
    560539                const std::vector< std::string > names;
    561540
     
    579558        }
    580559
    581         std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ) {
     560        std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt ) {
    582561                ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } };
    583562                maybe_accept( stmt, finder );
     
    717696                template <typename Predicate>
    718697                bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) {
    719                         std::vector< const ast::Expr * > callExprs = collectCtorDtorCalls( stmt );
     698                        std::vector< ast::ptr< ast::Expr > > callExprs = collectCtorDtorCalls( stmt );
    720699                        return std::all_of( callExprs.begin(), callExprs.end(), pred );
    721700                }
     
    960939        }
    961940
    962         // looks like some other such codegen uses UntypedExpr and does not create fake function. should revisit afterwards
    963         // following passes may accidentally resolve this expression if returned as untyped...
    964         ast::Expr * createBitwiseAssignment (const ast::Expr * dst, const ast::Expr * src) {
    965                 static ast::ptr<ast::FunctionDecl> assign = nullptr;
    966                 if (!assign) {
    967                         auto td = new ast::TypeDecl({}, "T", {}, nullptr, ast::TypeDecl::Dtype, true);
    968                         assign = new ast::FunctionDecl({}, "?=?", {},
    969                         { new ast::ObjectDecl({}, "_dst", new ast::ReferenceType(new ast::TypeInstType("T", td))),
    970                           new ast::ObjectDecl({}, "_src", new ast::TypeInstType("T", td))},
    971                         { new ast::ObjectDecl({}, "_ret", new ast::TypeInstType("T", td))}, nullptr, {}, ast::Linkage::Intrinsic);
    972                 }
    973                 if (dst->result.as<ast::ReferenceType>()) {
    974                         for (int depth = dst->result->referenceDepth(); depth > 0; depth--) {
    975                                 dst = new ast::AddressExpr(dst);
    976                         }
    977                 }
    978                 else {
    979                         dst = new ast::CastExpr(dst, new ast::ReferenceType(dst->result, {}));
    980                 }
    981                 if (src->result.as<ast::ReferenceType>()) {
    982                         for (int depth = src->result->referenceDepth(); depth > 0; depth--) {
    983                                 src = new ast::AddressExpr(src);
    984                         }
    985                 }
    986                 return new ast::ApplicationExpr(dst->location, ast::VariableExpr::functionPointer(dst->location, assign), {dst, src});
    987         }
    988 
    989941        struct ConstExprChecker : public WithShortCircuiting {
    990942                // most expressions are not const expr
     
    11031055                return isCopyFunction( decl, "?{}" );
    11041056        }
    1105 
    1106         void addDataSectonAttribute( ObjectDecl * objDecl ) {
    1107                 Type *strLitT = new PointerType( Type::Qualifiers( ),
    1108                         new BasicType( Type::Qualifiers( ), BasicType::Char ) );
    1109                 std::list< Expression * > attr_params;
    1110                 attr_params.push_back(
    1111                         new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) );
    1112                 objDecl->attributes.push_back(new Attribute("section", attr_params));
    1113         }
    1114 
    11151057}
  • src/InitTweak/InitTweak.h

    rf7e4f8e8 rb9537e6  
    3838        /// returns the first parameter of a constructor/destructor/assignment function
    3939        ObjectDecl * getParamThis( FunctionType * ftype );
    40         const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func);
    4140
    4241        /// generate a bitwise assignment operation.
    4342        ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src );
    44 
    45         ast::Expr * createBitwiseAssignment( const ast::Expr * dst, const ast::Expr * src);
    4643
    4744        /// transform Initializer into an argument list that can be passed to a call expression
     
    5148        /// True if the resolver should try to construct dwt
    5249        bool tryConstruct( DeclarationWithType * dwt );
    53         bool tryConstruct( const ast::DeclWithType * dwt );
    5450
    5551        /// True if the type can have a user-defined constructor
    5652        bool isConstructable( Type * t );
    57         bool isConstructable( const ast::Type * t );
    5853
    5954        /// True if the Initializer contains designations
     
    8479        /// get all Ctor/Dtor call expressions from a Statement
    8580        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
    86         std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt );
     81        std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt );
    8782
    8883        /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
     
    107102        bool isConstExpr( Expression * expr );
    108103        bool isConstExpr( Initializer * init );
    109 
    110         /// Modifies objDecl to have:
    111         ///    __attribute__((section (".data#")))
    112         /// which makes gcc put the declared variable in the data section,
    113         /// which is helpful for global constants on newer gcc versions,
    114         /// so that CFA's generated initialization won't segfault when writing it via a const cast.
    115         /// The trailing # is an injected assembly comment, to suppress the "a" in
    116         ///    .section .data,"a"
    117         ///    .section .data#,"a"
    118         /// to avoid assembler warning "ignoring changed section attributes for .data"
    119         void addDataSectonAttribute( ObjectDecl * objDecl );
    120104
    121105        class InitExpander_old {
  • src/InitTweak/module.mk

    rf7e4f8e8 rb9537e6  
    2323        InitTweak/GenInit.h \
    2424        InitTweak/InitTweak.cc \
    25         InitTweak/InitTweak.h \
    26         InitTweak/FixInitNew.cpp
     25        InitTweak/InitTweak.h
    2726
    2827SRCDEMANGLE += \
  • src/Parser/ParseNode.h

    rf7e4f8e8 rb9537e6  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Oct 24 03:53:54 2020
    13 // Update Count     : 895
     12// Last Modified On : Mon Jul  6 09:33:32 2020
     13// Update Count     : 892
    1414//
    1515
     
    205205struct TypeData;
    206206
    207 struct DeclarationNode : public ParseNode {
     207class DeclarationNode : public ParseNode {
     208  public:
    208209        // These enumerations must harmonize with their names in DeclarationNode.cc.
    209210        enum BasicType { Void, Bool, Char, Int, Int128,
     
    303304        bool get_inLine() const { return inLine; }
    304305        DeclarationNode * set_inLine( bool inL ) { inLine = inL; return this; }
    305 
     306  public:
    306307        DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }
    307308
     
    359360//##############################################################################
    360361
    361 struct StatementNode final : public ParseNode {
     362class StatementNode final : public ParseNode {
     363  public:
    362364        StatementNode() { stmt = nullptr; }
    363365        StatementNode( Statement * stmt ) : stmt( stmt ) {}
     
    380382                os << stmt.get() << std::endl;
    381383        }
    382 
     384  private:
    383385        std::unique_ptr<Statement> stmt;
    384386}; // StatementNode
     
    424426Statement * build_finally( StatementNode * stmt );
    425427Statement * build_compound( StatementNode * first );
    426 StatementNode * maybe_build_compound( StatementNode * first );
    427428Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr );
    428429Statement * build_directive( std::string * directive );
  • src/Parser/StatementNode.cc

    rf7e4f8e8 rb9537e6  
    1010// Created On       : Sat May 16 14:59:41 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Oct 24 04:20:55 2020
    13 // Update Count     : 383
     12// Last Modified On : Sat Aug  4 09:39:25 2018
     13// Update Count     : 363
    1414//
    1515
     
    345345} // build_compound
    346346
    347 // A single statement in a control structure is always converted to a compound statement so subsequent generated code
    348 // can be placed within this compound statement. Otherwise, code generation has to constantly check for a single
    349 // statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a
    350 // conical form for code generation.
    351 StatementNode * maybe_build_compound( StatementNode * first ) {
    352         // Optimization: if the control-structure statement is a compound statement, do not wrap it.
    353         // e.g., if (...) {...} do not wrap the existing compound statement.
    354         if ( ! dynamic_cast<CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
    355                 CompoundStmt * cs = new CompoundStmt();
    356                 buildMoveList( first, cs->get_kids() );
    357                 return new StatementNode( cs );
    358         } // if
    359         return first;
    360 } // maybe_build_compound
    361 
    362347Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
    363348        std::list< Expression * > out, in;
  • src/Parser/parser.yy

    rf7e4f8e8 rb9537e6  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Oct 24 08:21:14 2020
    13 // Update Count     : 4624
     12// Last Modified On : Fri Oct  9 18:09:09 2020
     13// Update Count     : 4614
    1414//
    1515
     
    10801080        IF '(' if_control_expression ')' statement                      %prec THEN
    10811081                // explicitly deal with the shift/reduce conflict on if/else
    1082                 { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), nullptr ) ); }
     1082                { $$ = new StatementNode( build_if( $3, $5, nullptr ) ); }
    10831083        | IF '(' if_control_expression ')' statement ELSE statement
    1084                 { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), maybe_build_compound( $7 ) ) ); }
     1084                { $$ = new StatementNode( build_if( $3, $5, $7 ) ); }
    10851085        ;
    10861086
     
    11301130
    11311131case_clause:                                                                                    // CFA
    1132         case_label_list statement                                       { $$ = $1->append_last_case( maybe_build_compound( $2 ) ); }
     1132        case_label_list statement                                       { $$ = $1->append_last_case( new StatementNode( build_compound( $2 ) ) ); }
    11331133        ;
    11341134
     
    11481148iteration_statement:
    11491149        WHILE '(' push if_control_expression ')' statement pop
    1150                 { $$ = new StatementNode( build_while( $4, maybe_build_compound( $6 ) ) ); }
     1150                { $$ = new StatementNode( build_while( $4, $6 ) ); }
    11511151        | WHILE '(' ')' statement                                                       // CFA => while ( 1 )
    1152                 { $$ = new StatementNode( build_while( new IfCtrl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); }
     1152                { $$ = new StatementNode( build_while( new IfCtrl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), $4 ) ); }
    11531153        | DO statement WHILE '(' comma_expression ')' ';'
    1154                 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
     1154                { $$ = new StatementNode( build_do_while( $5, $2 ) ); }
    11551155        | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
    1156                 { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); }
     1156                { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), $2 ) ); }
    11571157        | FOR '(' push for_control_expression_list ')' statement pop
    1158                 { $$ = new StatementNode( build_for( $4, maybe_build_compound( $6 ) ) ); }
     1158                { $$ = new StatementNode( build_for( $4, $6 ) ); }
    11591159        | FOR '(' ')' statement                                                         // CFA => for ( ;; )
    1160                 { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); }
     1160                { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), $4 ) ); }
    11611161        ;
    11621162
     
    13411341waitfor_clause:
    13421342        when_clause_opt waitfor statement                                       %prec THEN
    1343                 { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1 ); }
     1343                { $$ = build_waitfor( $2, $3, $1 ); }
    13441344        | when_clause_opt waitfor statement WOR waitfor_clause
    1345                 { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1, $5 ); }
     1345                { $$ = build_waitfor( $2, $3, $1, $5 ); }
    13461346        | when_clause_opt timeout statement                                     %prec THEN
    1347                 { $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1 ); }
     1347                { $$ = build_waitfor_timeout( $2, $3, $1 ); }
    13481348        | when_clause_opt ELSE statement
    1349                 { $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); }
     1349                { $$ = build_waitfor_timeout( nullptr, $3, $1 ); }
    13501350                // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    13511351        | when_clause_opt timeout statement WOR ELSE statement
    13521352                { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    13531353        | when_clause_opt timeout statement WOR when_clause ELSE statement
    1354                 { $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1, maybe_build_compound( $7 ), $5 ); }
     1354                { $$ = build_waitfor_timeout( $2, $3, $1, $7, $5 ); }
    13551355        ;
    13561356
  • src/ResolvExpr/Resolver.cc

    rf7e4f8e8 rb9537e6  
    11051105                }
    11061106
    1107                
    1108         } // anonymous namespace
    1109 /// Establish post-resolver invariants for expressions
     1107                /// Establish post-resolver invariants for expressions
    11101108                void finishExpr(
    11111109                        ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env,
     
    11201118                        StripCasts_new::strip( expr );
    11211119                }
     1120        } // anonymous namespace
     1121
    11221122
    11231123        ast::ptr< ast::Expr > resolveInVoidContext(
     
    11391139        }
    11401140
    1141         /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
     1141        namespace {
     1142                /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
    11421143                /// context.
    11431144                ast::ptr< ast::Expr > findVoidExpression(
     
    11501151                        return newExpr;
    11511152                }
    1152 
    1153         namespace {
    1154                
    11551153
    11561154                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
     
    11641162                        CandidateRef choice =
    11651163                                findUnfinishedKindExpression( untyped, symtab, kind, pred, mode );
    1166                         ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env );
     1164                        finishExpr( choice->expr, choice->env, untyped->env );
    11671165                        return std::move( choice->expr );
    11681166                }
  • src/ResolvExpr/Resolver.h

    rf7e4f8e8 rb9537e6  
    6666        ast::ptr< ast::Expr > findSingleExpression(
    6767                const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab );
    68         ast::ptr< ast::Expr > findVoidExpression(
    69                 const ast::Expr * untyped, const ast::SymbolTable & symtab);
    7068        /// Resolves a constructor init expression
    7169        ast::ptr< ast::Init > resolveCtorInit(
  • src/SymTab/Autogen.cc

    rf7e4f8e8 rb9537e6  
    233233        }
    234234
    235         // shallow copy the pointer list for return
    236         std::vector<ast::ptr<ast::TypeDecl>> getGenericParams (const ast::Type * t) {
    237                 if (auto structInst = dynamic_cast<const ast::StructInstType*>(t)) {
    238                         return structInst->base->params;
    239                 }
    240                 if (auto unionInst = dynamic_cast<const ast::UnionInstType*>(t)) {
    241                         return unionInst->base->params;
    242                 }
    243                 return {};
    244         }
    245 
    246235        /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
    247236        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) {
     
    255244                ftype->parameters.push_back( dstParam );
    256245                return ftype;
    257         }
    258 
    259         ///
    260         ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic) {
    261                 std::vector<ast::ptr<ast::TypeDecl>> typeParams;
    262                 if (maybePolymorphic) typeParams = getGenericParams(paramType);
    263                 auto dstParam = new ast::ObjectDecl(loc, "_dst", new ast::ReferenceType(paramType), nullptr, {}, ast::Linkage::Cforall);
    264                 return new ast::FunctionDecl(loc, fname, std::move(typeParams), {dstParam}, {}, new ast::CompoundStmt(loc));
    265246        }
    266247
  • src/SymTab/Autogen.h

    rf7e4f8e8 rb9537e6  
    5555        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
    5656        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
    57 
    58         ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true);
    5957
    6058        /// generate the type of a copy constructor for paramType.
  • src/SynTree/Expression.h

    rf7e4f8e8 rb9537e6  
    163163};
    164164
    165 /// VariableExpr represents an expression that simply refers to the value of a named variable.
    166 /// Does not take ownership of var.
    167 class VariableExpr : public Expression {
    168   public:
    169         DeclarationWithType * var;
    170 
    171         VariableExpr();
    172         VariableExpr( DeclarationWithType * var );
    173         VariableExpr( const VariableExpr & other );
    174         virtual ~VariableExpr();
    175 
    176         bool get_lvalue() const final;
    177 
    178         DeclarationWithType * get_var() const { return var; }
    179         void set_var( DeclarationWithType * newValue ) { var = newValue; }
    180 
    181         static VariableExpr * functionPointer( FunctionDecl * decl );
    182 
    183         virtual VariableExpr * clone() const override { return new VariableExpr( * this ); }
    184         virtual void accept( Visitor & v ) override { v.visit( this ); }
    185         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    186         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    187         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    188 };
    189 
    190165// The following classes are used to represent expression types that cannot be converted into
    191166// function-call format.
     
    354329};
    355330
     331/// VariableExpr represents an expression that simply refers to the value of a named variable.
     332/// Does not take ownership of var.
     333class VariableExpr : public Expression {
     334  public:
     335        DeclarationWithType * var;
     336
     337        VariableExpr();
     338        VariableExpr( DeclarationWithType * var );
     339        VariableExpr( const VariableExpr & other );
     340        virtual ~VariableExpr();
     341
     342        bool get_lvalue() const final;
     343
     344        DeclarationWithType * get_var() const { return var; }
     345        void set_var( DeclarationWithType * newValue ) { var = newValue; }
     346
     347        static VariableExpr * functionPointer( FunctionDecl * decl );
     348
     349        virtual VariableExpr * clone() const override { return new VariableExpr( * this ); }
     350        virtual void accept( Visitor & v ) override { v.visit( this ); }
     351        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     352        virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     353        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     354};
     355
    356356/// ConstantExpr represents an expression that simply refers to the value of a constant
    357357class ConstantExpr : public Expression {
  • src/main.cc

    rf7e4f8e8 rb9537e6  
    343343                        auto transUnit = convert( move( translationUnit ) );
    344344                        PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
    345                         if ( exprp ) {
    346                                 translationUnit = convert( move( transUnit ) );
    347                                 dump( translationUnit );
    348                                 return EXIT_SUCCESS;
    349                         } // if
    350 
    351                         PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary()));
    352345                        translationUnit = convert( move( transUnit ) );
    353346                } else {
    354347                        PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
    355                         if ( exprp ) {
    356                                 dump( translationUnit );
    357                                 return EXIT_SUCCESS;
    358                         }
    359 
    360                         PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) );
    361348                }
    362349
     350                if ( exprp ) {
     351                        dump( translationUnit );
     352                        return EXIT_SUCCESS;
     353                } // if
     354
    363355                // fix ObjectDecl - replaces ConstructorInit nodes
     356                PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) );
    364357                if ( ctorinitp ) {
    365358                        dump ( translationUnit );
  • tests/.expect/const-init.txt

    rf7e4f8e8 rb9537e6  
    1 almost done
    2 dtor
     1done
  • tests/complex.cfa

    rf7e4f8e8 rb9537e6  
    1414//
    1515
     16#include <stdio.h>
    1617#include <complex.h>
    1718#ifdef __CFA__
  • tests/const-init.cfa

    rf7e4f8e8 rb9537e6  
    1616/*
    1717
    18 These tests show non-crashing of generated code for constants with interesting initializers.
     18This test shows non-crashing of generated code for constants with interesting initizers.
    1919The potential for these to crash is compiler dependent.
    2020
    2121There are two cases:
    22 1. static constants in one compilation unit (tested here, in a few sub-cases)
     221. static constants in one compilation unit (tested here)
    23232. extern constants across compilation units (tested by libcfa being loadable, specifically
    24    the constant definitions in libcfa/src/limits.cfa, which almost every test exercises,
     24   the constant declarations in libcfa/src/limits.cfa, which almost every test exercises,
    2525   including "hello;" but notably, the "limits" test does not exercise it because that test
    2626   is compile-only)
     
    3737GCC-10 on Ubuntu 20.04    Has crashed      Has crashed
    3838
    39 For this test to fail, with most other tests passing, would be a situation only ever
     39For this test case to fail, with most other tests passing, would be a situation only ever
    4040observed with GCC-8.
    4141
    4242*/
    4343
    44 // initailized by generated function, called before main
    4544static const char foo = -1;
    4645
    47 struct thing{};
    48 void ^?{}( thing & ) { printf("dtor\n"); }
    49 
    5046int main() {
    51     // foo is already initialized
    52 
    53     // no dtor => stays a (static) local, initialized here
    54     static const char bar = -1;
    55 
    56     // has dtor => becomes a global, ctor called here, dtor called at exit
    57     static const thing it;
    58 
    59     printf("almost done\n");
     47    printf("done\n");
    6048}
  • tests/exceptions/cancel/coroutine.cfa

    rf7e4f8e8 rb9537e6  
    11// Try cancelling a coroutine.
    22
     3#include <stdio.h>
    34#include <coroutine.hfa>
    45#include <exception.hfa>
  • tests/exceptions/conditional.cfa

    rf7e4f8e8 rb9537e6  
    55
    66#include <exception.hfa>
     7#include <stdio.h>
    78
    89VTABLE_DECLARATION(num_error)(
  • tests/exceptions/except-io.hfa

    rf7e4f8e8 rb9537e6  
    11// Common tools for the exception tests.
     2
     3#include <stdio.h>
    24
    35// Echo when a destructor is run and an area/block is left.
  • tests/exceptions/trash.cfa

    rf7e4f8e8 rb9537e6  
    22
    33#include <exception.hfa>
     4#include <stdio.h>
    45
    56TRIVIAL_EXCEPTION(yin);
  • tests/global-monomorph.cfa

    rf7e4f8e8 rb9537e6  
    1 // Create monomorphic instances of polymorphic types at global scope.
     1// Crea
     2
     3#include <stdlib.hfa>
     4#include <stdio.h>
    25
    36forall(dtype T)
  • tests/poly-d-cycle.cfa

    rf7e4f8e8 rb9537e6  
    11// Check that a cycle of polymorphic dtype structures can be instancated.
     2
     3#include <stdio.h>
    24
    35forall(dtype T)
  • tests/poly-o-cycle.cfa

    rf7e4f8e8 rb9537e6  
    11// Check that a cycle of polymorphic otype structures can be instancated.
     2
     3#include <stdio.h>
    24
    35forall(otype T)
Note: See TracChangeset for help on using the changeset viewer.