Changes in / [f7e4f8e8:b9537e6]
- Files:
-
- 10 deleted
- 71 edited
-
Jenkinsfile (modified) (4 diffs)
-
benchmark/readyQ/cycle.cfa (deleted)
-
benchmark/readyQ/cycle.cpp (deleted)
-
benchmark/readyQ/cycle.go (deleted)
-
benchmark/readyQ/rq_bench.hfa (deleted)
-
benchmark/rmit.py (deleted)
-
doc/papers/concurrency/mail2 (modified) (2 diffs)
-
doc/proposals/vtable.md (modified) (1 diff)
-
doc/theses/andrew_beach_MMath/thesis-frontpgs.tex (modified) (3 diffs)
-
doc/theses/andrew_beach_MMath/uw-ethesis.cls (modified) (5 diffs)
-
libcfa/prelude/builtins.c (modified) (1 diff)
-
libcfa/src/concurrency/coroutine.cfa (modified) (6 diffs)
-
libcfa/src/concurrency/exception.cfa (modified) (3 diffs)
-
libcfa/src/concurrency/exception.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/invoke.h (modified) (1 diff)
-
libcfa/src/concurrency/io/setup.cfa (modified) (1 diff)
-
libcfa/src/concurrency/kernel.cfa (modified) (6 diffs)
-
libcfa/src/concurrency/kernel.hfa (modified) (1 diff)
-
libcfa/src/concurrency/kernel/startup.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/kernel_private.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/monitor.cfa (modified) (1 diff)
-
libcfa/src/concurrency/thread.cfa (modified) (4 diffs)
-
libcfa/src/concurrency/thread.hfa (modified) (3 diffs)
-
libcfa/src/exception.c (modified) (3 diffs)
-
libcfa/src/exception.h (modified) (4 diffs)
-
libcfa/src/stdhdr/unwind.h (deleted)
-
src/AST/Convert.cpp (modified) (19 diffs)
-
src/AST/Decl.cpp (modified) (1 diff)
-
src/AST/Decl.hpp (modified) (1 diff)
-
src/AST/DeclReplacer.cpp (modified) (3 diffs)
-
src/AST/DeclReplacer.hpp (modified) (1 diff)
-
src/AST/Expr.cpp (modified) (4 diffs)
-
src/AST/Expr.hpp (modified) (6 diffs)
-
src/AST/Fwd.hpp (modified) (1 diff)
-
src/AST/Node.hpp (modified) (1 diff)
-
src/AST/Pass.hpp (modified) (5 diffs)
-
src/AST/Pass.impl.hpp (modified) (8 diffs)
-
src/AST/SymbolTable.cpp (modified) (1 diff)
-
src/AST/SymbolTable.hpp (modified) (1 diff)
-
src/AST/TranslationUnit.hpp (deleted)
-
src/AST/Type.cpp (modified) (1 diff)
-
src/AST/Type.hpp (modified) (3 diffs)
-
src/AST/porting.md (modified) (5 diffs)
-
src/Common/PassVisitor.h (modified) (2 diffs)
-
src/Common/PassVisitor.impl.h (modified) (6 diffs)
-
src/Common/utility.h (modified) (1 diff)
-
src/Concurrency/Keywords.cc (modified) (9 diffs)
-
src/GenPoly/GenPoly.cc (modified) (9 diffs)
-
src/GenPoly/GenPoly.h (modified) (4 diffs)
-
src/GenPoly/Specialize.cc (modified) (1 diff)
-
src/InitTweak/FixGlobalInit.cc (modified) (5 diffs)
-
src/InitTweak/FixGlobalInit.h (modified) (2 diffs)
-
src/InitTweak/FixInit.cc (modified) (2 diffs)
-
src/InitTweak/FixInit.h (modified) (2 diffs)
-
src/InitTweak/FixInitNew.cpp (deleted)
-
src/InitTweak/GenInit.cc (modified) (1 diff)
-
src/InitTweak/GenInit.h (modified) (1 diff)
-
src/InitTweak/InitTweak.cc (modified) (7 diffs)
-
src/InitTweak/InitTweak.h (modified) (4 diffs)
-
src/InitTweak/module.mk (modified) (1 diff)
-
src/Parser/ParseNode.h (modified) (6 diffs)
-
src/Parser/StatementNode.cc (modified) (2 diffs)
-
src/Parser/parser.yy (modified) (5 diffs)
-
src/ResolvExpr/Resolver.cc (modified) (5 diffs)
-
src/ResolvExpr/Resolver.h (modified) (1 diff)
-
src/SymTab/Autogen.cc (modified) (2 diffs)
-
src/SymTab/Autogen.h (modified) (1 diff)
-
src/SynTree/Expression.h (modified) (2 diffs)
-
src/main.cc (modified) (1 diff)
-
tests/.expect/const-init.txt (modified) (1 diff)
-
tests/complex.cfa (modified) (1 diff)
-
tests/const-init.cfa (modified) (2 diffs)
-
tests/exceptions/cancel/.expect/thread.txt (deleted)
-
tests/exceptions/cancel/coroutine.cfa (modified) (1 diff)
-
tests/exceptions/cancel/thread.cfa (deleted)
-
tests/exceptions/conditional.cfa (modified) (1 diff)
-
tests/exceptions/except-io.hfa (modified) (1 diff)
-
tests/exceptions/trash.cfa (modified) (1 diff)
-
tests/global-monomorph.cfa (modified) (1 diff)
-
tests/poly-d-cycle.cfa (modified) (1 diff)
-
tests/poly-o-cycle.cfa (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
Jenkinsfile
rf7e4f8e8 rb9537e6 127 127 } 128 128 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}" 132 130 133 131 // Configure libcfa … … 361 359 public final CC_Desc Compiler 362 360 public final Arch_Desc Architecture 363 public final Boolean NewAST364 361 public final Boolean RunAllTests 365 362 public final Boolean RunBenchmark … … 413 410 414 411 this.IsSandbox = (branch == "jenkins-sandbox") 415 this.NewAST = param.NewAST416 412 this.RunAllTests = param.RunAllTests 417 413 this.RunBenchmark = param.RunBenchmark … … 474 470 ], \ 475 471 [$class: 'BooleanParameterDefinition', \ 476 description: 'If true, build compiler using new AST', \477 name: 'NewAST', \478 defaultValue: false, \479 ], \480 [$class: 'BooleanParameterDefinition', \481 472 description: 'If false, only the quick test suite is ran', \ 482 473 name: 'RunAllTests', \ 483 474 defaultValue: false, \ 484 ], 475 ], \ 485 476 [$class: 'BooleanParameterDefinition', \ 486 477 description: 'If true, jenkins also runs benchmarks', \ -
doc/papers/concurrency/mail2
rf7e4f8e8 rb9537e6 1 2 1 Date: Wed, 26 Jun 2019 20:12:38 +0000 3 2 From: Aaron Thomas <onbehalfof@manuscriptcentral.com> … … 1075 1074 Software: Practice and Experience Editorial Office 1076 1075 1077 1078 1079 Date: Thu, 15 Oct 2020 13:48:52 +00001080 From: Richard Jones <onbehalfof@manuscriptcentral.com>1081 Reply-To: R.E.Jones@kent.ac.uk1082 To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca1083 Subject: Software: Practice and Experience - Decision on Manuscript ID1084 SPE-19-0219.R31085 1086 15-Oct-20201087 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 Richard1100 1101 Prof. Richard Jones1102 Editor, Software: Practice and Experience1103 R.E.Jones@kent.ac.uk1104 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 +00001112 From: Mayank Roy Chowdhury <onbehalfof@manuscriptcentral.com>1113 Reply-To: speoffice@wiley.com1114 To: pabuhr@uwaterloo.ca1115 Subject: Manuscript Accepted - Please submit final updates to SPE-19-0219.R3 [email ref: ENR-AW-1-c]1116 1117 16-Oct-20201118 1119 Dear Dr. Buhr,1120 1121 Manuscript id: SPE-19-0219.R31122 Manuscript title: Advanced Control-flow and Concurrency in Cforall1123 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 document1130 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 Office1147 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 +00001154 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 Regards1164 1165 Mayank Roy Chowdhury1166 Editorial Assistant1167 Software practice and Experience1168 ________________________________1169 From: Peter A. Buhr <pabuhr@uwaterloo.ca>1170 Sent: Sunday, October 18, 2020 2:00 PM1171 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 the1188 final version of the PDF and source files using the mechanism on the "File1189 Upload" page and submitted that.1190 1191 1192 1193 Date: Tue, 20 Oct 2020 13:28:37 +05301194 To: "Dr. Peter Buhr" <pabuhr@uwaterloo.ca>1195 From: jpcms@spi-global.com1196 Subject: Information: Production Editor Contact Software:Practice and Experience | Advanced Control-flow and Concurrency in C A1197 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 Wiley1207 1208 Article ID: SPE_29251209 Article DOI: 10.1002/SPE.29251210 1211 1212 1213 Date: Tue, 20 Oct 2020 10:33:04 +00001214 From: <cs-author@wiley.com>1215 To: <pabuhr@uwaterloo.ca>1216 Subject: In Production: Your article accepted in Software: Practice and Experience1217 1218 Dear Peter Buhr,1219 1220 Article ID: SPE29251221 Article DOI: 10.1002/spe.29251222 Internal Article ID: 169222131223 Article: Advanced Control-flow and Concurrency in C A1224 Journal: Software: Practice and Experience1225 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-new1233 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 article1237 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 Services1241 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 +00001247 From: <cs-author@wiley.com>1248 To: <pabuhr@uwaterloo.ca>1249 Subject: You have actions to complete in Author Services1250 1251 Dear Peter Buhr,1252 1253 Article ID: SPE29251254 Article DOI: 10.1002/spe.29251255 Internal Article ID: 169222131256 Article: Advanced Control-flow and Concurrency in C A1257 Journal: Software: Practice and Experience1258 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 Services1267 1268 1269 1270 Date: Thu, 22 Oct 2020 23:13:07 +00001271 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: SPE29251278 Article DOI: 10.1002/spe.29251279 Internal Article ID: 169222131280 Article: Advanced Control-flow and Concurrency in C A1281 Journal: Software: Practice and Experience1282 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 512 512 possibly like the one used to create the assertion. 513 513 514 ### Extension: Associated Types Use515 If the `associated_types.md` proposal is accepted the following trait could516 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 find525 the (possibly default) virtual table. It is required to construct instances526 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 the535 user has to explicately provide the table's name as it doesn't really have its536 own type name. If it does it is probably mangled.537 538 514 ### Virtual Tables as Types 539 515 Here we consider encoding plus the implementation of functions on it to be a -
doc/theses/andrew_beach_MMath/thesis-frontpgs.tex
rf7e4f8e8 rb9537e6 5 5 % TITLE PAGE 6 6 %---------------------------------------------------------------------- 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 }15 7 16 8 \pagestyle{empty} … … 23 15 \vspace*{1.0cm} 24 16 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 29 23 by \\ 30 24 31 25 \vspace*{1.0cm} 32 26 33 {\Large \eprint{author}} \\ 27 \Large 28 Pat Neugraad \\ 34 29 35 30 \vspace*{3.0cm} 36 31 32 \normalsize 37 33 A thesis \\ 38 34 presented to the University of Waterloo \\ 39 35 in fulfillment of the \\ 40 36 thesis requirement for the degree of \\ 41 \eprint{degree}\\37 Doctor of Philosophy \\ 42 38 in \\ 43 \eprint{program}\\39 Zoology \\ 44 40 45 41 \vspace*{2.0cm} … … 49 45 \vspace*{1.0cm} 50 46 51 \copyright {} \eprint{author}2017 \\47 \copyright\ Pat Neugraad 2017 \\ 52 48 \end{center} 53 49 \end{titlepage} -
doc/theses/andrew_beach_MMath/uw-ethesis.cls
rf7e4f8e8 rb9537e6 19 19 % 20 20 % Exported Names: 21 % \ethesissetup{<key-value-pairs>}22 % Preforms set-up (or a reconfiguration) of the document class. See the23 % Set-Up Keys section for the keys that may be passed in. Use commas to24 % seperate key-value-pairs.25 %26 21 % \ifformat{<format>}{<true>}{<false>} 27 22 % If the document's format is <format> than expands to <true> otherwise … … 32 27 % initial setup depends on the document format but they can be overriden 33 28 % 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. This37 % 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|phd46 % faculty=ahs|arts|eng|env|math|sci47 29 \NeedsTeXFormat{LaTeX2e} 48 \ProvidesClass{uw-ethesis}[2020/ 10/25 v0.2UW-eThesis Template Document Class]30 \ProvidesClass{uw-ethesis}[2020/03/24 v0.1 UW-eThesis Template Document Class] 49 31 50 32 \RequirePackage{etoolbox} 51 \RequirePackage{xkeyval}52 33 53 34 % 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}} 57 38 58 39 \ProcessOptions\relax … … 100 81 % a recto page. This will often require an empty verso (left-hand side) page 101 82 % that should not have the page number printed on it. 102 \let\ ethesis@origdoublepage\cleardoublepage83 \let\origdoublepage\cleardoublepage 103 84 \newcommand{\clearemptydoublepage}{% 104 \clearpage{\pagestyle{empty}\ ethesis@origdoublepage}}85 \clearpage{\pagestyle{empty}\origdoublepage}} 105 86 \let\cleardoublepage\clearemptydoublepage 106 87 … … 108 89 \renewcommand*{\bibname}{References} 109 90 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}} 130 96 131 97 % Includes the hyperref package loading a number of defaults. … … 140 106 pdfstartview={FitH}, % Fits the width of the page to the window. 141 107 } 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}}}{} 146 112 \ifformat{print}{ 147 113 \hypersetup{ -
libcfa/prelude/builtins.c
rf7e4f8e8 rb9537e6 9 9 // Author : Peter A. Buhr 10 10 // Created On : Fri Jul 21 16:21:03 2017 11 // Last Modified By : Andrew Beach12 // Last Modified On : Tue Oct 27 14:42:00202013 // Update Count : 11 111 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Oct 9 18:26:19 2020 13 // Update Count : 110 14 14 // 15 16 #define __cforall_builtins__17 15 18 16 // 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 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Oct 23 23:05:24202013 // Update Count : 2 212 // Last Modified On : Tue May 26 22:06:09 2020 13 // Update Count : 21 14 14 // 15 15 … … 24 24 #include <unistd.h> 25 25 #include <sys/mman.h> // mprotect 26 extern "C" { 27 // use this define to make unwind.h play nice, definitely a hack 28 #define HIDE_EXPORTS 26 29 #include <unwind.h> 30 #undef HIDE_EXPORTS 31 } 27 32 28 33 #include "kernel_private.hfa" 29 #include "exception.hfa"30 34 31 35 #define __CFA_INVOKE_PRIVATE__ … … 45 49 FORALL_DATA_INSTANCE(CoroutineCancelled, (dtype coroutine_t), (coroutine_t)) 46 50 51 struct __cfaehm_node { 52 struct _Unwind_Exception unwind_exception; 53 struct __cfaehm_node * next; 54 int handler_index; 55 }; 56 47 57 forall(dtype T) 48 58 void mark_exception(CoroutineCancelled(T) *) {} … … 50 60 forall(dtype T) 51 61 void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) { 52 dst->virtual_table = src->virtual_table;53 62 dst->the_coroutine = src->the_coroutine; 54 63 dst->the_exception = src->the_exception; … … 65 74 verify( desc->cancellation ); 66 75 desc->state = Cancelled; 67 exception_t * except = __cfaehm_cancellation_exception( desc->cancellation);76 exception_t * except = (exception_t *)(1 + (__cfaehm_node *)desc->cancellation); 68 77 69 78 // TODO: Remove explitate vtable set once trac#186 is fixed. … … 208 217 size = libFloor(create_size - stack_data_size - diff, libAlign()); 209 218 } // 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 ); 211 220 212 221 this->storage = (__stack_t *)((intptr_t)storage + size); -
libcfa/src/concurrency/exception.cfa
rf7e4f8e8 rb9537e6 10 10 // Created On : Mon Aug 17 10:41:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Oct 28 14:34:00 202013 // Update Count : 112 // Last Modified On : Tue Aug 25 14:41:00 2020 13 // Update Count : 0 14 14 // 15 15 16 #define __cforall_thread__ 16 extern "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 } 17 22 23 #include "invoke.h" 18 24 #include "exception.hfa" 19 20 25 #include "coroutine.hfa" 21 26 22 27 extern struct $thread * mainThread; 23 extern "C" {24 extern void __cfactx_thrd_leave();25 }26 28 27 29 // Common pattern for all the stop functions, wait until the end then act. … … 50 52 51 53 STOP_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(); 54 56 ) 55 57 … … 83 85 stop_param = (void *)0x22; 84 86 } else { 85 this_thread->self_cor.cancellation = unwind_exception;86 87 87 stop_func = thread_cancelstop; 88 88 stop_param = this_thread; -
libcfa/src/concurrency/exception.hfa
rf7e4f8e8 rb9537e6 16 16 #pragma once 17 17 18 // This is an internal bridge between the two modes and must be C compatable.19 20 #include <unwind.h>21 18 #include "bits/defs.hfa" 22 19 #include "invoke.h" 23 #include "exception.h"24 20 25 21 #ifdef __cforall 26 22 extern "C" { 23 24 #define HIDE_EXPORTS 27 25 #endif 26 #include "unwind.h" 28 27 29 28 struct exception_context_t * this_exception_context(void) OPTIONAL_THREAD; … … 33 32 34 33 #ifdef __cforall 34 #undef HIDE_EXPORTS 35 35 } 36 36 #endif -
libcfa/src/concurrency/invoke.h
rf7e4f8e8 rb9537e6 157 157 158 158 // current execution status for coroutine 159 // Possible values are:160 // - TICKET_BLOCKED (-1) thread is blocked161 // - TICKET_RUNNING ( 0) thread is running162 // - TICKET_UNBLOCK ( 1) thread should ignore next block163 159 volatile int ticket; 164 160 enum __Coroutine_State state:8; -
libcfa/src/concurrency/io/setup.cfa
rf7e4f8e8 rb9537e6 250 250 // Fixup the thread state 251 251 thrd.state = Blocked; 252 thrd.ticket = TICKET_BLOCKED;252 thrd.ticket = 0; 253 253 thrd.preempted = __NO_PREEMPTION; 254 254 -
libcfa/src/concurrency/kernel.cfa
rf7e4f8e8 rb9537e6 252 252 /* paranoid */ verify( kernelTLS.this_thread == thrd_dst ); 253 253 /* paranoid */ verify( thrd_dst->context.SP ); 254 /* paranoid */ verify( thrd_dst->state != Halted );255 254 /* 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 256 255 /* 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 … … 288 287 if(unlikely(thrd_dst->state == Halted)) { 289 288 // 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; 292 292 break RUNNING; 293 293 } … … 299 299 int old_ticket = __atomic_fetch_sub(&thrd_dst->ticket, 1, __ATOMIC_SEQ_CST); 300 300 switch(old_ticket) { 301 case TICKET_RUNNING:301 case 1: 302 302 // This is case 1, the regular case, nothing more is needed 303 303 break RUNNING; 304 case TICKET_UNBLOCK:304 case 2: 305 305 // This is case 2, the racy case, someone tried to run this thread before it finished blocking 306 306 // In this case, just run it again. … … 410 410 int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST); 411 411 switch(old_ticket) { 412 case TICKET_RUNNING:412 case 1: 413 413 // Wake won the race, the thread will reschedule/rerun itself 414 414 break; 415 case TICKET_BLOCKED:415 case 0: 416 416 /* paranoid */ verify( ! thrd->preempted != __NO_PREEMPTION ); 417 417 /* paranoid */ verify( thrd->state == Blocked ); … … 422 422 default: 423 423 // 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(); 425 425 } 426 426 } … … 448 448 } 449 449 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 451 void __leave_thread() { 452 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 453 returnToKernel(); 454 abort(); 474 455 } 475 456 -
libcfa/src/concurrency/kernel.hfa
rf7e4f8e8 rb9537e6 79 79 // Handle to pthreads 80 80 pthread_t kernel_thread; 81 82 // RunThread data 83 // Action to do after a thread is ran 84 $thread * destroyer; 81 85 82 86 // Preemption data -
libcfa/src/concurrency/kernel/startup.cfa
rf7e4f8e8 rb9537e6 441 441 442 442 static void ?{}( $thread & this, current_stack_info_t * info) with( this ) { 443 ticket = TICKET_RUNNING;443 ticket = 1; 444 444 state = Start; 445 445 self_cor{ info }; … … 474 474 this.cltr = &_cltr; 475 475 full_proc = true; 476 destroyer = 0p; 476 477 do_terminate = false; 477 478 preemption_alarm = 0p; -
libcfa/src/concurrency/kernel_private.hfa
rf7e4f8e8 rb9537e6 39 39 ; 40 40 41 // release/wake-up the following resources42 void __ thread_finish( $thread * thrd);41 //Block current thread and release/wake-up the following resources 42 void __leave_thread() __attribute__((noreturn)); 43 43 44 44 //----------------------------------------------------------------------------- … … 65 65 // KERNEL ONLY unpark with out disabling interrupts 66 66 void __unpark( struct __processor_id_t *, $thread * thrd ); 67 68 #define TICKET_BLOCKED (-1) // thread is blocked69 #define TICKET_RUNNING ( 0) // thread is running70 #define TICKET_UNBLOCK ( 1) // thread should ignore next block71 67 72 68 static inline bool __post(single_sem & this, struct __processor_id_t * id) { -
libcfa/src/concurrency/monitor.cfa
rf7e4f8e8 rb9537e6 281 281 } 282 282 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 ); 283 extern "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 329 forall( dtype T | is_thread(T) ) 330 T & 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 } 308 337 } 309 338 -
libcfa/src/concurrency/thread.cfa
rf7e4f8e8 rb9537e6 19 19 20 20 #include "kernel_private.hfa" 21 #include "exception.hfa"22 21 23 22 #define __CFA_INVOKE_PRIVATE__ … … 29 28 context{ 0p, 0p }; 30 29 self_cor{ name, storage, storageSize }; 31 ticket = TICKET_RUNNING;30 ticket = 1; 32 31 state = Start; 33 32 preempted = __NO_PREEMPTION; … … 57 56 unregister(curr_cluster, this); 58 57 ^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){};115 58 } 116 59 … … 150 93 } 151 94 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 159 95 // Local Variables: // 160 96 // mode: c // -
libcfa/src/concurrency/thread.hfa
rf7e4f8e8 rb9537e6 22 22 #include "kernel.hfa" 23 23 #include "monitor.hfa" 24 #include "exception.hfa"25 24 26 25 //----------------------------------------------------------------------------- 27 26 // thread trait 28 27 trait 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); 32 31 }; 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) *);44 32 45 33 // define that satisfies the trait without using the thread keyword … … 77 65 static inline void ?{}($thread & this, const char * const name, struct cluster & cl ) { this{ name, cl, 0p, 65000 }; } 78 66 static 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 );87 67 88 68 //----------------------------------------------------------------------------- … … 128 108 //---------- 129 109 // join 130 forall( dtype T | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)))110 forall( dtype T | is_thread(T) ) 131 111 T & join( T & this ); 132 112 -
libcfa/src/exception.c
rf7e4f8e8 rb9537e6 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Jun 26 15:13:00 2017 11 // Last Modified By : Andrew Beach12 // Last Modified On : Tue Oct 27 16:27:00202013 // Update Count : 3 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Aug 29 15:52:22 2020 13 // Update Count : 34 14 14 // 15 15 … … 17 17 #include <stddef.h> // for size_t 18 18 19 #include <unwind.h> // for struct _Unwind_Exception {...};20 21 19 #include "exception.h" 22 20 23 21 #include <stdlib.h> 24 22 #include <stdio.h> 23 #include <unwind.h> 25 24 #include <bits/debug.hfa> 26 25 #include "concurrency/invoke.h" … … 114 113 115 114 // MEMORY MANAGEMENT ========================================================= 115 116 struct __cfaehm_node { 117 struct _Unwind_Exception unwind_exception; 118 struct __cfaehm_node * next; 119 int handler_index; 120 }; 116 121 117 122 #define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node))) -
libcfa/src/exception.h
rf7e4f8e8 rb9537e6 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // exception.h -- Internal exception handling definitions.7 // exception.h -- Builtins for exception handling. 8 8 // 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Jun 26 15:11:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Oct 27 14:45:00 202013 // Update Count : 1 112 // Last Modified On : Tue May 19 14:17:00 2020 13 // Update Count : 10 14 14 // 15 15 16 16 #pragma once 17 17 18 // This could be considered several headers. All are internal to the exception19 // system but needed to depending on whether they are C/Cforall code and20 // whether or not they are part of the builtins.21 18 22 19 #ifdef __cforall 23 20 extern "C" { 24 21 #endif 25 26 // Included in C code or the built-ins.27 #if !defined(__cforall) || defined(__cforall_builtins__)28 22 29 23 struct __cfaehm_base_exception_t; … … 53 47 // Function catches termination exceptions. 54 48 void __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)); 58 52 59 53 // Clean-up the exception in catch blocks. … … 62 56 // Data structure creates a list of resume handlers. 63 57 struct __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); 66 60 }; 67 61 68 62 // These act as constructor and destructor for the resume node. 69 63 void __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)); 72 66 void __cfaehm_try_resume_cleanup( 73 struct __cfaehm_try_resume_node * node);67 struct __cfaehm_try_resume_node * node); 74 68 75 69 // Check for a standard way to call fake deconstructors. 76 70 struct __cfaehm_cleanup_hook {}; 77 71 78 #endif79 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 #endif93 94 72 #ifdef __cforall 95 73 } 96 97 // Built-ins not visible in C.98 #if defined(__cforall_builtins__)99 74 100 75 // Not all the built-ins can be expressed in C. These can't be … … 149 124 150 125 #endif 151 152 #endif -
src/AST/Convert.cpp
rf7e4f8e8 rb9537e6 47 47 48 48 //================================================================================================ 49 namespace ast{49 namespace { 50 50 51 51 // This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not) 52 52 // 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 now56 53 ast::Type * sizeType = nullptr; 57 54 ast::FunctionDecl * dereferenceOperator = nullptr; … … 66 63 using Cache = std::unordered_map< const ast::Node *, BaseSyntaxNode * >; 67 64 Cache cache; 68 69 // Statements can no longer be shared.70 // however, since StmtExprResult is now implemented, need to still maintain71 // readonly references.72 Cache readonlyCache;73 65 74 66 template<typename T> … … 162 154 } 163 155 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 ); 165 161 if ( inCache( node ) ) { 166 162 return nullptr; 167 163 } 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 172 164 auto decl = new ObjectDecl( 173 165 node->name, … … 176 168 bfwd, 177 169 type->clone(), 178 nullptr, // prevent infinite loop170 init, 179 171 attr, 180 172 Type::FuncSpecifiers( node->funcSpec.val ) 181 173 ); 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 ); 191 175 } 192 176 … … 221 205 decl->statements = get<CompoundStmt>().accept1( node->stmts ); 222 206 decl->withExprs = get<Expression>().acceptL( node->withExprs ); 223 if ( ast::dereferenceOperator == node ) {207 if ( dereferenceOperator == node ) { 224 208 Validate::dereferenceOperator = decl; 225 209 } 226 if ( ast::dtorStructDestroy == node ) {210 if ( dtorStructDestroy == node ) { 227 211 Validate::dtorStructDestroy = decl; 228 212 } … … 283 267 ); 284 268 285 if ( ast::dtorStruct == node ) {269 if ( dtorStruct == node ) { 286 270 Validate::dtorStruct = decl; 287 271 } … … 336 320 337 321 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 ); 341 323 stmt->location = node->location; 342 324 stmt->labels = makeLabelL( stmt, node->labels ); … … 355 337 if ( inCache( node ) ) return nullptr; 356 338 auto stmt = new ExprStmt( nullptr ); 339 cache.emplace( node, stmt ); 357 340 stmt->expr = get<Expression>().accept1( node->expr ); 358 341 return stmtPostamble( stmt, node ); … … 1028 1011 auto stmts = node->stmts; 1029 1012 // 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 } 1032 1016 auto rslt = new StmtExpr( 1033 1017 get<CompoundStmt>().accept1(stmts) … … 1036 1020 rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls); 1037 1021 rslt->dtors = get<Expression>().acceptL(node->dtors); 1038 if (node->resultExpr) {1039 // this MUST be found by children visit1040 rslt->resultExpr = strict_dynamic_cast<ExprStmt *>(readonlyCache.at(node->resultExpr));1041 }1042 1022 1043 1023 auto expr = visitBaseExpr( node, rslt ); … … 1056 1036 1057 1037 auto expr = visitBaseExpr( node, rslt ); 1058 this->node = expr ->clone();1038 this->node = expr; 1059 1039 return nullptr; 1060 1040 } … … 1146 1126 auto type = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind }; 1147 1127 // I believe this should always be a BasicType. 1148 if ( ast::sizeType == node ) {1128 if ( sizeType == node ) { 1149 1129 Validate::SizeType = type; 1150 1130 } … … 1549 1529 1550 1530 // function type is now derived from parameter decls instead of storing them 1551 1552 /*1553 1531 auto ftype = new ast::FunctionType((ast::ArgumentFlag)old->type->isVarArgs, cv(old->type)); 1554 1532 ftype->params.reserve(paramVars.size()); … … 1562 1540 } 1563 1541 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); 1568 1543 1569 1544 auto decl = new ast::FunctionDecl{ … … 1571 1546 old->name, 1572 1547 // GET_ACCEPT_1(type, FunctionType), 1573 std::move(forall),1574 1548 std::move(paramVars), 1575 1549 std::move(returnVars), … … 1578 1552 { old->linkage.val }, 1579 1553 GET_ACCEPT_V(attributes, Attribute), 1580 { old->get_funcSpec().val }, 1581 old->type->isVarArgs 1554 { old->get_funcSpec().val } 1582 1555 }; 1583 1556 1584 //decl->type = ftype;1557 decl->type = ftype; 1585 1558 cache.emplace( old, decl ); 1586 1559 … … 1597 1570 1598 1571 if ( Validate::dereferenceOperator == old ) { 1599 ast::dereferenceOperator = decl;1572 dereferenceOperator = decl; 1600 1573 } 1601 1574 1602 1575 if ( Validate::dtorStructDestroy == old ) { 1603 ast::dtorStructDestroy = decl;1576 dtorStructDestroy = decl; 1604 1577 } 1605 1578 } … … 1626 1599 1627 1600 if ( Validate::dtorStruct == old ) { 1628 ast::dtorStruct = decl;1601 dtorStruct = decl; 1629 1602 } 1630 1603 } … … 2558 2531 // I believe this should always be a BasicType. 2559 2532 if ( Validate::SizeType == old ) { 2560 ast::sizeType = type;2533 sizeType = type; 2561 2534 } 2562 2535 visitType( old, type ); -
src/AST/Decl.cpp
rf7e4f8e8 rb9537e6 48 48 49 49 // --- 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 69 50 70 51 const Type * FunctionDecl::get_type() const { return type.get(); } -
src/AST/Decl.hpp
rf7e4f8e8 rb9537e6 131 131 std::vector< ptr<Expr> > withExprs; 132 132 133 FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall,133 FunctionDecl( const CodeLocation & loc, const std::string & name, 134 134 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 135 135 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 ) {} 139 139 140 140 const Type * get_type() const override; -
src/AST/DeclReplacer.cpp
rf7e4f8e8 rb9537e6 38 38 const ast::TypeInstType * previsit( const ast::TypeInstType * ); 39 39 }; 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 };50 40 } 51 41 … … 64 54 DeclMap declMap; 65 55 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 );71 56 } 72 57 … … 103 88 return ninst; 104 89 } 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 112 90 } 113 91 } -
src/AST/DeclReplacer.hpp
rf7e4f8e8 rb9537e6 23 23 class DeclWithType; 24 24 class TypeDecl; 25 class Expr;26 25 27 26 namespace DeclReplacer { 28 27 using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >; 29 28 using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >; 30 using ExprMap = std::unordered_map< const DeclWithType *, const Expr * >;31 29 32 30 const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false ); 33 31 const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false ); 34 32 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);36 33 } 37 34 } -
src/AST/Expr.cpp
rf7e4f8e8 rb9537e6 67 67 // --- UntypedExpr 68 68 69 UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, constExpr * arg ) {69 UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, Expr * arg ) { 70 70 assert( arg ); 71 71 … … 92 92 } 93 93 94 UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, const Expr * lhs, constExpr * rhs ) {94 UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs ) { 95 95 assert( lhs && rhs ); 96 96 … … 102 102 } 103 103 return ret; 104 }105 106 // --- VariableExpr107 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 pointer126 VariableExpr * funcExpr = new VariableExpr{ loc, decl };127 funcExpr->result = new PointerType{ funcExpr->result };128 return funcExpr;129 104 } 130 105 … … 263 238 } 264 239 240 // --- VariableExpr 241 242 VariableExpr::VariableExpr( const CodeLocation & loc ) 243 : Expr( loc ), var( nullptr ) {} 244 245 VariableExpr::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 252 bool VariableExpr::get_lvalue() const { 253 // It isn't always an lvalue, but it is never an rvalue. 254 return true; 255 } 256 257 VariableExpr * 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 265 265 // --- ConstantExpr 266 266 -
src/AST/Expr.hpp
rf7e4f8e8 rb9537e6 226 226 227 227 /// Creates a new dereference expression 228 static UntypedExpr * createDeref( const CodeLocation & loc, constExpr * arg );228 static UntypedExpr * createDeref( const CodeLocation & loc, Expr * arg ); 229 229 /// Creates a new assignment expression 230 static UntypedExpr * createAssign( const CodeLocation & loc, const Expr * lhs, constExpr * rhs );230 static UntypedExpr * createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs ); 231 231 232 232 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 247 247 private: 248 248 NameExpr * clone() const override { return new NameExpr{ *this }; } 249 MUTATE_FRIEND250 };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 function263 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 }; }268 249 MUTATE_FRIEND 269 250 }; … … 411 392 }; 412 393 394 /// A reference to a named variable. 395 class VariableExpr final : public Expr { 396 public: 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 ); } 408 private: 409 VariableExpr * clone() const override { return new VariableExpr{ *this }; } 410 MUTATE_FRIEND 411 }; 412 413 413 /// A compile-time constant. 414 414 /// Mostly carries C-source text from parse to code-gen, without interpretation. E.g. strings keep their outer quotes and never have backslashes interpreted. … … 422 422 const CodeLocation & loc, const Type * ty, const std::string & r, 423 423 std::optional<unsigned long long> i ) 424 : Expr( loc, ty ), rep( r ), ival( i ) , underlyer(ty){}424 : Expr( loc, ty ), rep( r ), ival( i ) {} 425 425 426 426 /// Gets the integer value of this constant, if one is appropriate to its type. … … 617 617 618 618 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 ); } 620 620 621 621 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 742 742 std::vector<ptr<Expr>> dtors; ///< destructor(s) for return variable(s) 743 743 744 readonly<ExprStmt> resultExpr;745 746 744 StmtExpr( const CodeLocation & loc, const CompoundStmt * ss ); 747 745 -
src/AST/Fwd.hpp
rf7e4f8e8 rb9537e6 137 137 typedef unsigned int UniqueId; 138 138 139 extern Type * sizeType;140 extern FunctionDecl * dereferenceOperator;141 extern StructDecl * dtorStruct;142 extern FunctionDecl * dtorStructDestroy;143 144 139 } -
src/AST/Node.hpp
rf7e4f8e8 rb9537e6 49 49 50 50 bool unique() const { return strong_count == 1; } 51 bool isManaged() const {return strong_count > 0; }52 51 53 52 private: -
src/AST/Pass.hpp
rf7e4f8e8 rb9537e6 228 228 template<typename core_type> 229 229 friend void accept_all( std::list< ptr<Decl> > & decls, Pass<core_type>& visitor ); 230 231 bool isInFunction() const {232 return inFunction;233 }234 235 230 private: 236 231 … … 240 235 const ast::Stmt * call_accept( const ast::Stmt * ); 241 236 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 *);246 237 247 238 template< typename node_t > … … 266 257 template<typename node_t, typename parent_t, typename child_t> 267 258 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);271 259 272 260 private: … … 296 284 private: 297 285 bool inFunction = false; 298 bool atFunctionTop = false;299 286 }; 300 287 … … 384 371 struct WithVisitorRef { 385 372 Pass<core_t> * const visitor = nullptr; 386 387 bool isInFunction() const {388 return visitor->isInFunction();389 }390 373 }; 391 374 -
src/AST/Pass.impl.hpp
rf7e4f8e8 rb9537e6 167 167 __pedantic_pass_assert( stmt ); 168 168 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 177 169 // add a few useful symbols to the scope 178 170 using __pass::empty; … … 332 324 333 325 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::*child349 ) {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 );358 326 359 327 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR"); … … 502 470 // foralls are still in function type 503 471 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 505 474 ValueGuard< bool > oldInFunction( inFunction ); 506 475 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;511 476 maybe_accept( node, &FunctionDecl::stmts ); 512 477 maybe_accept( node, &FunctionDecl::attributes ); … … 675 640 VISIT_START( node ); 676 641 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); 682 647 }); 683 648 ValueGuard< bool > guard2( inFunction ); … … 738 703 maybe_accept( node, &IfStmt::inits ); 739 704 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 ); 742 707 }) 743 708 … … 756 721 maybe_accept( node, &WhileStmt::inits ); 757 722 maybe_accept( node, &WhileStmt::cond ); 758 maybe_accept _as_compound( node, &WhileStmt::body );723 maybe_accept( node, &WhileStmt::body ); 759 724 }) 760 725 … … 771 736 // for statements introduce a level of scope (for the initialization) 772 737 guard_symtab guard { *this }; 773 // xxx - old ast does not create WithStmtsToAdd scope for loop inits. should revisit this later.774 738 maybe_accept( node, &ForStmt::inits ); 775 739 maybe_accept( node, &ForStmt::cond ); 776 740 maybe_accept( node, &ForStmt::inc ); 777 maybe_accept _as_compound( node, &ForStmt::body );741 maybe_accept( node, &ForStmt::body ); 778 742 }) 779 743 … … 870 834 maybe_accept( node, &CatchStmt::decl ); 871 835 maybe_accept( node, &CatchStmt::cond ); 872 maybe_accept _as_compound( node, &CatchStmt::body );836 maybe_accept( node, &CatchStmt::body ); 873 837 }) 874 838 -
src/AST/SymbolTable.cpp
rf7e4f8e8 rb9537e6 335 335 } 336 336 337 338 void SymbolTable::addFunction ( const FunctionDecl * func) {339 addTypes( f unc->type->forall );340 addIds( f unc->returns );341 addIds( f unc->params );342 } 343 337 /* 338 void SymbolTable::addFunctionType( const FunctionType * ftype ) { 339 addTypes( ftype->forall ); 340 addIds( ftype->returns ); 341 addIds( ftype->params ); 342 } 343 */ 344 344 345 345 void SymbolTable::lazyInitScope() { -
src/AST/SymbolTable.hpp
rf7e4f8e8 rb9537e6 145 145 146 146 /// 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 ); 148 148 149 149 private: -
src/AST/Type.cpp
rf7e4f8e8 rb9537e6 157 157 158 158 template<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>165 159 bool SueInstType<decl_t>::isComplete() const { 166 160 return base ? base->body : false; -
src/AST/Type.hpp
rf7e4f8e8 rb9537e6 302 302 class FunctionType final : public ParameterizedType { 303 303 public: 304 // std::vector<ptr<DeclWithType>> returns; 305 // std::vector<ptr<DeclWithType>> params; 306 304 307 std::vector<ptr<Type>> returns; 305 308 std::vector<ptr<Type>> params; … … 342 345 : ParameterizedType(q, std::move(as)), params(), name(n) {} 343 346 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 349 347 BaseInstType( const BaseInstType & o ); 350 348 … … 371 369 372 370 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 = {} ); 378 372 379 373 bool isComplete() const override; -
src/AST/porting.md
rf7e4f8e8 rb9537e6 30 30 * Base nodes now override `const Node * accept( Visitor & v ) const = 0` with, e.g. `const Stmt * accept( Visitor & v ) const override = 0` 31 31 * `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`36 32 37 33 ## Structural Changes ## … … 150 146 * allows `newObject` as just default settings 151 147 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 157 148 `NamedTypeDecl` 158 149 * `parameters` => `params` … … 163 154 `AggregateDecl` 164 155 * `parameters` => `params` 165 166 `StructDecl`167 * `makeInst` replaced by better constructor on `StructInstType`.168 156 169 157 `Expr` … … 257 245 * **TODO** move `kind`, `typeNames` into code generator 258 246 259 `ReferenceToType` => `BaseInstType`247 `ReferenceToType` 260 248 * deleted `get_baseParameters()` from children 261 249 * replace with `aggr() ? aggr()->params : nullptr` … … 273 261 * `returnVals` => `returns` 274 262 * `parameters` => `params` 275 * Both now just point at types.276 263 * `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`281 264 282 265 `TypeInstType` -
src/Common/PassVisitor.h
rf7e4f8e8 rb9537e6 354 354 virtual TypeSubstitution * mutate( TypeSubstitution * sub ) final; 355 355 356 bool isInFunction() const {357 return inFunction;358 }359 360 356 private: 361 357 bool inFunction = false; 362 bool atFunctionTop = false;363 358 364 359 template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor ); … … 531 526 public: 532 527 PassVisitor<pass_type> * const visitor = nullptr; 533 534 bool isInFunction() const {535 return visitor->isInFunction();536 }537 528 }; 538 529 -
src/Common/PassVisitor.impl.h
rf7e4f8e8 rb9537e6 532 532 indexerAddId( &func ); 533 533 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 535 536 ValueGuard< bool > oldInFunction( inFunction ); 536 537 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;541 538 maybeAccept_impl( node->statements, *this ); 542 539 maybeAccept_impl( node->attributes, *this ); … … 570 567 indexerAddId( &func ); 571 568 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 573 571 ValueGuard< bool > oldInFunction( inFunction ); 574 572 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;579 573 maybeAccept_impl( node->statements, *this ); 580 574 maybeAccept_impl( node->attributes, *this ); … … 607 601 indexerAddId( &func ); 608 602 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 610 605 ValueGuard< bool > oldInFunction( inFunction ); 611 606 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;616 607 maybeMutate_impl( node->statements, *this ); 617 608 maybeMutate_impl( node->attributes, *this ); … … 1016 1007 VISIT_START( node ); 1017 1008 { 1018 // Do not enter a new scope if atFunctionTop is true, don't leave one either.1019 ValueGuard< bool > old AtFunctionTop( 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(); } ); 1021 1012 auto guard2 = makeFuncGuard( [this]() { call_beginScope(); }, [this]() { call_endScope(); } ); 1022 atFunctionTop= false;1013 inFunction = false; 1023 1014 visitStatementList( node->kids ); 1024 1015 } … … 1030 1021 VISIT_START( node ); 1031 1022 { 1032 // Do not enter a new scope if atFunctionTop is true, don't leave one either.1033 ValueGuard< bool > old AtFunctionTop( 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(); } ); 1035 1026 auto guard2 = makeFuncGuard( [this]() { call_beginScope(); }, [this]() { call_endScope(); } ); 1036 atFunctionTop= false;1027 inFunction = false; 1037 1028 visitStatementList( node->kids ); 1038 1029 } … … 1044 1035 MUTATE_START( node ); 1045 1036 { 1046 // Do not enter a new scope if atFunctionTop is true, don't leave one either.1047 ValueGuard< bool > old AtFunctionTop( 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(); } ); 1049 1040 auto guard2 = makeFuncGuard( [this]() { call_beginScope(); }, [this]() { call_endScope(); } ); 1050 atFunctionTop= false;1041 inFunction = false; 1051 1042 mutateStatementList( node->kids ); 1052 1043 } -
src/Common/utility.h
rf7e4f8e8 rb9537e6 360 360 reverse_iterate_t( T & ref ) : ref(ref) {} 361 361 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(); } 366 365 }; 367 366 -
src/Concurrency/Keywords.cc
rf7e4f8e8 rb9537e6 46 46 } 47 47 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 56 48 //============================================================================================= 57 49 // Pass declarations … … 127 119 "get_thread", 128 120 "thread keyword requires threads to be in scope, add #include <thread.hfa>\n", 129 " ThreadCancelled",121 "", 130 122 true, 131 123 AggregateDecl::Thread … … 298 290 std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first ); 299 291 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 * > &); 303 294 304 295 static void implement( std::list< Declaration * > & translationUnit ) { … … 311 302 StructDecl* guard_decl = nullptr; 312 303 StructDecl* dtor_guard_decl = nullptr; 313 StructDecl* thread_guard_decl = nullptr;314 304 315 305 static std::unique_ptr< Type > generic_func; … … 811 801 bool first = false; 812 802 std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first ); 813 bool constisDtor = CodeGen::isDestructor( decl->name );803 bool isDtor = CodeGen::isDestructor( decl->name ); 814 804 815 805 // Is this function relevant to monitors … … 859 849 860 850 // 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 ); 869 853 } 870 854 else { 871 addStat ements( decl, body, mutexArgs );855 addStatments( decl, body, mutexArgs ); 872 856 } 873 857 } … … 886 870 assert( !dtor_guard_decl ); 887 871 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;892 872 } 893 873 } … … 928 908 } 929 909 930 void MutexKeyword::addDtorStat ements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {910 void MutexKeyword::addDtorStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) { 931 911 Type * arg_type = args.front()->get_type()->clone(); 932 912 arg_type->set_mutex( false ); … … 977 957 978 958 //$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 ) { 1019 963 ObjectDecl * monitors = new ObjectDecl( 1020 964 "__monitors", -
src/GenPoly/GenPoly.cc
rf7e4f8e8 rb9537e6 46 46 } 47 47 48 bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const ast::TypeSubstitution * env) {49 for (auto ¶m : params) {50 auto paramType = param.strict_as<ast::TypeExpr>();51 if (isPolyType(paramType->type, env)) return true;52 }53 return false;54 }55 56 48 /// Checks a parameter list for polymorphic parameters from tyVars; will substitute according to env if present 57 49 bool hasPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) { … … 64 56 } 65 57 66 bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const TyVarMap & tyVars, const ast::TypeSubstitution * env) {67 for (auto ¶m : params) {68 auto paramType = param.strict_as<ast::TypeExpr>();69 if (isPolyType(paramType->type, tyVars, env)) return true;70 }71 return false;72 }73 74 58 /// Checks a parameter list for dynamic-layout parameters from tyVars; will substitute according to env if present 75 59 bool hasDynParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) { … … 108 92 Type *newType = env->lookup( typeInst->get_name() ); 109 93 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;119 94 } 120 95 return type; … … 136 111 } 137 112 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 153 113 Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) { 154 114 type = replaceTypeInst( type, env ); … … 166 126 } 167 127 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;183 128 } 184 129 … … 504 449 } 505 450 506 namespace {507 // temporary hack to avoid re-implementing anything related to TyVarMap508 // 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 514 451 bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) { 515 452 // is parameter is not polymorphic, don't need to box … … 522 459 } 523 460 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 box526 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 533 461 bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) { 534 462 FunctionType * function = getFunctionType( appExpr->function->result ); … … 539 467 } 540 468 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 550 469 void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) { 551 470 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}));556 471 } 557 472 … … 563 478 if ( PointerType *pointer = dynamic_cast< PointerType* >( type ) ) { 564 479 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);577 480 } 578 481 } -
src/GenPoly/GenPoly.h
rf7e4f8e8 rb9537e6 26 26 27 27 namespace GenPoly { 28 typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap; 28 29 29 typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;30 30 /// Replaces a TypeInstType by its referrent in the environment, if applicable 31 31 Type* replaceTypeInst( Type* type, const TypeSubstitution* env ); … … 33 33 /// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided 34 34 Type *isPolyType( Type *type, const TypeSubstitution *env = 0 ); 35 const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env = nullptr);36 35 37 36 /// returns polymorphic type if is polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided 38 37 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);40 38 41 39 /// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided … … 86 84 /// true if arg requires boxing given exprTyVars 87 85 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);89 86 90 87 /// true if arg requires boxing in the call to appExpr 91 88 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);93 89 94 90 /// Adds the type variable `tyVar` to `tyVarMap` … … 97 93 /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap` 98 94 void makeTyVarMap( Type *type, TyVarMap &tyVarMap ); 99 void makeTyVarMap(const ast::Type * type, TyVarMap & tyVarMap);100 95 101 96 /// Prints type variable map -
src/GenPoly/Specialize.cc
rf7e4f8e8 rb9537e6 218 218 thunkFunc->get_attributes().push_back( new Attribute( "unused" ) ); 219 219 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 224 220 // thread thunk parameters into call to actual function, naming thunk parameters as we go 225 221 UniqueName paramNamer( paramPrefix ); -
src/InitTweak/FixGlobalInit.cc
rf7e4f8e8 rb9537e6 34 34 #include "SynTree/Visitor.h" // for acceptAll, Visitor 35 35 36 #include "AST/Expr.hpp"37 #include "AST/Node.hpp"38 #include "AST/Pass.hpp"39 40 36 namespace InitTweak { 41 37 class GlobalFixer : public WithShortCircuiting { … … 54 50 FunctionDecl * initFunction; 55 51 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;70 52 }; 71 53 … … 109 91 } 110 92 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 } // if123 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 } // if132 }133 134 93 void GlobalFixer::previsit( ObjectDecl *objDecl ) { 135 94 std::list< Statement * > & initStatements = initFunction->get_statements()->get_kids(); … … 153 112 } // if 154 113 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. 156 130 initStatements.push_back( ctor ); 157 131 objDecl->init = nullptr; … … 165 139 } // if 166 140 delete ctorInit; 167 } // if168 }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-NULL175 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, but180 // non-intrinsic dtors must be called181 destroyStmts.push_front( dtor );182 // ctorInit->dtor = nullptr;183 } // if184 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 okay193 mutDecl->init = nullptr;194 } // if195 // delete ctorInit;196 141 } // if 197 142 } -
src/InitTweak/FixGlobalInit.h
rf7e4f8e8 rb9537e6 19 19 #include <string> // for string 20 20 21 #include <AST/Fwd.hpp>22 23 24 21 class Declaration; 25 22 … … 29 26 /// function is for library code. 30 27 void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary ); 31 void fixGlobalInit( std::list< ast::ptr<ast::Decl> > & translationUnit, bool inLibrary );32 28 } // namespace 33 29 -
src/InitTweak/FixInit.cc
rf7e4f8e8 rb9537e6 219 219 }; 220 220 221 struct SplitExpressions : public WithShortCircuiting, /*public WithTypeSubstitution, */public WithStmtsToAdd {221 struct SplitExpressions : public WithShortCircuiting, public WithTypeSubstitution, public WithStmtsToAdd { 222 222 /// add CompoundStmts around top-level expressions so that temporaries are destroyed in the correct places. 223 223 static void split( std::list< Declaration * > &translationUnit ); … … 802 802 if ( Statement * ctor = ctorInit->get_ctor() ) { 803 803 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 810 804 // originally wanted to take advantage of gcc nested functions, but 811 805 // we get memory errors with this approach. To remedy this, the static -
src/InitTweak/FixInit.h
rf7e4f8e8 rb9537e6 19 19 #include <string> // for string 20 20 21 #include <AST/Fwd.hpp>22 23 21 class Declaration; 24 22 … … 26 24 /// replace constructor initializers with expression statements and unwrap basic C-style initializers 27 25 void fix( std::list< Declaration * > & translationUnit, bool inLibrary ); 28 29 void fix( std::list<ast::ptr<ast::Decl>> & translationUnit, bool inLibrary);30 26 } // namespace 31 27 -
src/InitTweak/GenInit.cc
rf7e4f8e8 rb9537e6 283 283 assert( stmts.size() <= 1 ); 284 284 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);292 285 } 293 286 -
src/InitTweak/GenInit.h
rf7e4f8e8 rb9537e6 33 33 /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument 34 34 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);36 35 37 36 /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer -
src/InitTweak/InitTweak.cc
rf7e4f8e8 rb9537e6 498 498 } 499 499 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 507 500 bool tryConstruct( DeclarationWithType * dwt ) { 508 501 ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt ); … … 518 511 } 519 512 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_extern526 && 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 534 513 struct CallFinder_old { 535 514 CallFinder_old( const std::list< std::string > & names ) : names( names ) {} … … 557 536 558 537 struct CallFinder_new final { 559 std::vector< const ast::Expr *> matches;538 std::vector< ast::ptr< ast::Expr > > matches; 560 539 const std::vector< std::string > names; 561 540 … … 579 558 } 580 559 581 std::vector< const ast::Expr *> collectCtorDtorCalls( const ast::Stmt * stmt ) {560 std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt ) { 582 561 ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } }; 583 562 maybe_accept( stmt, finder ); … … 717 696 template <typename Predicate> 718 697 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 ); 720 699 return std::all_of( callExprs.begin(), callExprs.end(), pred ); 721 700 } … … 960 939 } 961 940 962 // looks like some other such codegen uses UntypedExpr and does not create fake function. should revisit afterwards963 // 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 989 941 struct ConstExprChecker : public WithShortCircuiting { 990 942 // most expressions are not const expr … … 1103 1055 return isCopyFunction( decl, "?{}" ); 1104 1056 } 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 1115 1057 } -
src/InitTweak/InitTweak.h
rf7e4f8e8 rb9537e6 38 38 /// returns the first parameter of a constructor/destructor/assignment function 39 39 ObjectDecl * getParamThis( FunctionType * ftype ); 40 const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func);41 40 42 41 /// generate a bitwise assignment operation. 43 42 ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src ); 44 45 ast::Expr * createBitwiseAssignment( const ast::Expr * dst, const ast::Expr * src);46 43 47 44 /// transform Initializer into an argument list that can be passed to a call expression … … 51 48 /// True if the resolver should try to construct dwt 52 49 bool tryConstruct( DeclarationWithType * dwt ); 53 bool tryConstruct( const ast::DeclWithType * dwt );54 50 55 51 /// True if the type can have a user-defined constructor 56 52 bool isConstructable( Type * t ); 57 bool isConstructable( const ast::Type * t );58 53 59 54 /// True if the Initializer contains designations … … 84 79 /// get all Ctor/Dtor call expressions from a Statement 85 80 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 ); 87 82 88 83 /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call … … 107 102 bool isConstExpr( Expression * expr ); 108 103 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" in116 /// .section .data,"a"117 /// .section .data#,"a"118 /// to avoid assembler warning "ignoring changed section attributes for .data"119 void addDataSectonAttribute( ObjectDecl * objDecl );120 104 121 105 class InitExpander_old { -
src/InitTweak/module.mk
rf7e4f8e8 rb9537e6 23 23 InitTweak/GenInit.h \ 24 24 InitTweak/InitTweak.cc \ 25 InitTweak/InitTweak.h \ 26 InitTweak/FixInitNew.cpp 25 InitTweak/InitTweak.h 27 26 28 27 SRCDEMANGLE += \ -
src/Parser/ParseNode.h
rf7e4f8e8 rb9537e6 10 10 // Created On : Sat May 16 13:28:16 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Oct 24 03:53:54202013 // Update Count : 89 512 // Last Modified On : Mon Jul 6 09:33:32 2020 13 // Update Count : 892 14 14 // 15 15 … … 205 205 struct TypeData; 206 206 207 struct DeclarationNode : public ParseNode { 207 class DeclarationNode : public ParseNode { 208 public: 208 209 // These enumerations must harmonize with their names in DeclarationNode.cc. 209 210 enum BasicType { Void, Bool, Char, Int, Int128, … … 303 304 bool get_inLine() const { return inLine; } 304 305 DeclarationNode * set_inLine( bool inL ) { inLine = inL; return this; } 305 306 public: 306 307 DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); } 307 308 … … 359 360 //############################################################################## 360 361 361 struct StatementNode final : public ParseNode { 362 class StatementNode final : public ParseNode { 363 public: 362 364 StatementNode() { stmt = nullptr; } 363 365 StatementNode( Statement * stmt ) : stmt( stmt ) {} … … 380 382 os << stmt.get() << std::endl; 381 383 } 382 384 private: 383 385 std::unique_ptr<Statement> stmt; 384 386 }; // StatementNode … … 424 426 Statement * build_finally( StatementNode * stmt ); 425 427 Statement * build_compound( StatementNode * first ); 426 StatementNode * maybe_build_compound( StatementNode * first );427 428 Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr ); 428 429 Statement * build_directive( std::string * directive ); -
src/Parser/StatementNode.cc
rf7e4f8e8 rb9537e6 10 10 // Created On : Sat May 16 14:59:41 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Oct 24 04:20:55 202013 // Update Count : 3 8312 // Last Modified On : Sat Aug 4 09:39:25 2018 13 // Update Count : 363 14 14 // 15 15 … … 345 345 } // build_compound 346 346 347 // A single statement in a control structure is always converted to a compound statement so subsequent generated code348 // can be placed within this compound statement. Otherwise, code generation has to constantly check for a single349 // statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a350 // 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_ptr355 CompoundStmt * cs = new CompoundStmt();356 buildMoveList( first, cs->get_kids() );357 return new StatementNode( cs );358 } // if359 return first;360 } // maybe_build_compound361 362 347 Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) { 363 348 std::list< Expression * > out, in; -
src/Parser/parser.yy
rf7e4f8e8 rb9537e6 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Oct 24 08:21:14202013 // Update Count : 46 2412 // Last Modified On : Fri Oct 9 18:09:09 2020 13 // Update Count : 4614 14 14 // 15 15 … … 1080 1080 IF '(' if_control_expression ')' statement %prec THEN 1081 1081 // 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 ) ); } 1083 1083 | 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 ) ); } 1085 1085 ; 1086 1086 … … 1130 1130 1131 1131 case_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 ) ) ); } 1133 1133 ; 1134 1134 … … 1148 1148 iteration_statement: 1149 1149 WHILE '(' push if_control_expression ')' statement pop 1150 { $$ = new StatementNode( build_while( $4, maybe_build_compound( $6 )) ); }1150 { $$ = new StatementNode( build_while( $4, $6 ) ); } 1151 1151 | 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 ) ); } 1153 1153 | DO statement WHILE '(' comma_expression ')' ';' 1154 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 )) ); }1154 { $$ = new StatementNode( build_do_while( $5, $2 ) ); } 1155 1155 | 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 ) ); } 1157 1157 | 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 ) ); } 1159 1159 | 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 ) ); } 1161 1161 ; 1162 1162 … … 1341 1341 waitfor_clause: 1342 1342 when_clause_opt waitfor statement %prec THEN 1343 { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1 ); }1343 { $$ = build_waitfor( $2, $3, $1 ); } 1344 1344 | 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 ); } 1346 1346 | when_clause_opt timeout statement %prec THEN 1347 { $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1 ); }1347 { $$ = build_waitfor_timeout( $2, $3, $1 ); } 1348 1348 | when_clause_opt ELSE statement 1349 { $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); }1349 { $$ = build_waitfor_timeout( nullptr, $3, $1 ); } 1350 1350 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless) 1351 1351 | when_clause_opt timeout statement WOR ELSE statement 1352 1352 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; } 1353 1353 | 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 ); } 1355 1355 ; 1356 1356 -
src/ResolvExpr/Resolver.cc
rf7e4f8e8 rb9537e6 1105 1105 } 1106 1106 1107 1108 } // anonymous namespace 1109 /// Establish post-resolver invariants for expressions 1107 /// Establish post-resolver invariants for expressions 1110 1108 void finishExpr( 1111 1109 ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env, … … 1120 1118 StripCasts_new::strip( expr ); 1121 1119 } 1120 } // anonymous namespace 1121 1122 1122 1123 1123 ast::ptr< ast::Expr > resolveInVoidContext( … … 1139 1139 } 1140 1140 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` 1142 1143 /// context. 1143 1144 ast::ptr< ast::Expr > findVoidExpression( … … 1150 1151 return newExpr; 1151 1152 } 1152 1153 namespace {1154 1155 1153 1156 1154 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the … … 1164 1162 CandidateRef choice = 1165 1163 findUnfinishedKindExpression( untyped, symtab, kind, pred, mode ); 1166 ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env );1164 finishExpr( choice->expr, choice->env, untyped->env ); 1167 1165 return std::move( choice->expr ); 1168 1166 } -
src/ResolvExpr/Resolver.h
rf7e4f8e8 rb9537e6 66 66 ast::ptr< ast::Expr > findSingleExpression( 67 67 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);70 68 /// Resolves a constructor init expression 71 69 ast::ptr< ast::Init > resolveCtorInit( -
src/SymTab/Autogen.cc
rf7e4f8e8 rb9537e6 233 233 } 234 234 235 // shallow copy the pointer list for return236 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 246 235 /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *) 247 236 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) { … … 255 244 ftype->parameters.push_back( dstParam ); 256 245 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));265 246 } 266 247 -
src/SymTab/Autogen.h
rf7e4f8e8 rb9537e6 55 55 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic 56 56 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);59 57 60 58 /// generate the type of a copy constructor for paramType. -
src/SynTree/Expression.h
rf7e4f8e8 rb9537e6 163 163 }; 164 164 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 190 165 // The following classes are used to represent expression types that cannot be converted into 191 166 // function-call format. … … 354 329 }; 355 330 331 /// VariableExpr represents an expression that simply refers to the value of a named variable. 332 /// Does not take ownership of var. 333 class 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 356 356 /// ConstantExpr represents an expression that simply refers to the value of a constant 357 357 class ConstantExpr : public Expression { -
src/main.cc
rf7e4f8e8 rb9537e6 343 343 auto transUnit = convert( move( translationUnit ) ); 344 344 PASS( "Resolve", ResolvExpr::resolve( transUnit ) ); 345 if ( exprp ) {346 translationUnit = convert( move( transUnit ) );347 dump( translationUnit );348 return EXIT_SUCCESS;349 } // if350 351 PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary()));352 345 translationUnit = convert( move( transUnit ) ); 353 346 } else { 354 347 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() ) );361 348 } 362 349 350 if ( exprp ) { 351 dump( translationUnit ); 352 return EXIT_SUCCESS; 353 } // if 354 363 355 // fix ObjectDecl - replaces ConstructorInit nodes 356 PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) ); 364 357 if ( ctorinitp ) { 365 358 dump ( translationUnit ); -
tests/.expect/const-init.txt
rf7e4f8e8 rb9537e6 1 almost done 2 dtor 1 done -
tests/complex.cfa
rf7e4f8e8 rb9537e6 14 14 // 15 15 16 #include <stdio.h> 16 17 #include <complex.h> 17 18 #ifdef __CFA__ -
tests/const-init.cfa
rf7e4f8e8 rb9537e6 16 16 /* 17 17 18 Th ese tests show non-crashing of generated code for constants with interesting initializers.18 This test shows non-crashing of generated code for constants with interesting initizers. 19 19 The potential for these to crash is compiler dependent. 20 20 21 21 There are two cases: 22 1. static constants in one compilation unit (tested here , in a few sub-cases)22 1. static constants in one compilation unit (tested here) 23 23 2. extern constants across compilation units (tested by libcfa being loadable, specifically 24 the constant de finitions in libcfa/src/limits.cfa, which almost every test exercises,24 the constant declarations in libcfa/src/limits.cfa, which almost every test exercises, 25 25 including "hello;" but notably, the "limits" test does not exercise it because that test 26 26 is compile-only) … … 37 37 GCC-10 on Ubuntu 20.04 Has crashed Has crashed 38 38 39 For this test to fail, with most other tests passing, would be a situation only ever39 For this test case to fail, with most other tests passing, would be a situation only ever 40 40 observed with GCC-8. 41 41 42 42 */ 43 43 44 // initailized by generated function, called before main45 44 static const char foo = -1; 46 45 47 struct thing{};48 void ^?{}( thing & ) { printf("dtor\n"); }49 50 46 int 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"); 60 48 } -
tests/exceptions/cancel/coroutine.cfa
rf7e4f8e8 rb9537e6 1 1 // Try cancelling a coroutine. 2 2 3 #include <stdio.h> 3 4 #include <coroutine.hfa> 4 5 #include <exception.hfa> -
tests/exceptions/conditional.cfa
rf7e4f8e8 rb9537e6 5 5 6 6 #include <exception.hfa> 7 #include <stdio.h> 7 8 8 9 VTABLE_DECLARATION(num_error)( -
tests/exceptions/except-io.hfa
rf7e4f8e8 rb9537e6 1 1 // Common tools for the exception tests. 2 3 #include <stdio.h> 2 4 3 5 // Echo when a destructor is run and an area/block is left. -
tests/exceptions/trash.cfa
rf7e4f8e8 rb9537e6 2 2 3 3 #include <exception.hfa> 4 #include <stdio.h> 4 5 5 6 TRIVIAL_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> 2 5 3 6 forall(dtype T) -
tests/poly-d-cycle.cfa
rf7e4f8e8 rb9537e6 1 1 // Check that a cycle of polymorphic dtype structures can be instancated. 2 3 #include <stdio.h> 2 4 3 5 forall(dtype T) -
tests/poly-o-cycle.cfa
rf7e4f8e8 rb9537e6 1 1 // Check that a cycle of polymorphic otype structures can be instancated. 2 3 #include <stdio.h> 2 4 3 5 forall(otype T)
Note:
See TracChangeset
for help on using the changeset viewer.