Changeset 685a5e8
- Timestamp:
- Jun 7, 2016, 11:27:55 AM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- db175c8
- Parents:
- 2f6b7c9 (diff), d5f1cfc (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
Jenkinsfile
r2f6b7c9 r685a5e8 64 64 } 65 65 66 //Helper routine to collect information about the git history 67 def collect_git_info() { 68 69 def out_dir = pwd tmp: true 70 gitRefName = env.BRANCH_NAME 71 dir("../${gitRefName}@script") { 72 sh "git reflog > ${out_dir}/GIT_COMMIT" 73 } 74 git_reflog = readFile("${out_dir}/GIT_COMMIT") 75 gitRefOldValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][1] 76 gitRefNewValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][2] 77 } 78 66 79 //=========================================================================================================== 67 80 // Main loop of the compilation … … 72 85 def log_needed = false 73 86 currentBuild.result = "SUCCESS" 74 75 //Properties sent by the git-hooks (ref name, latest commit hash, previous commit hash) 76 properties( [[$class: 'ParametersDefinitionProperty', parameterDefinitions: \ 77 [[$class: 'StringParameterDefinition', name: 'GitRefName', defaultValue: 'master', description: 'name of the ref that changed' ], \ 78 [$class: 'StringParameterDefinition', name: 'GitRefNewValue', defaultValue: 'HEAD', description: 'new commit of the reference' ], \ 79 [$class: 'StringParameterDefinition', name: 'GitRefOldValue', defaultValue: 'HEAD~1', description: 'old commit of the reference']] \ 80 ]] ) 87 status_prefix = '' 81 88 82 89 try { 83 echo "Properties-start"84 echo "ref name : ${GitRefName}"85 echo "ref new value : ${GitRefNewValue}"86 echo "ref old value : ${GitRefOldValue}"87 echo "Properties-stop"88 89 90 //Prevent the build from exceeding 30 minutes 90 91 timeout(30) { … … 92 93 //Wrap build to add timestamp to command line 93 94 wrap([$class: 'TimestamperBuildWrapper']) { 95 96 collect_git_info() 94 97 95 98 //Compile using gcc-4.9 … … 107 110 } 108 111 } 109 110 112 } 111 113 … … 142 144 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase() 143 145 146 sh "git rev-list --format=short ${gitRefOldValue}...${gitRefNewValue} > GIT_LOG" 147 def gitLog = readFile('GIT_LOG') 148 149 sh "git diff --stat ${gitRefNewValue} ${gitRefOldValue} > GIT_DIFF" 150 def gitDiff = readFile('GIT_DIFF') 151 144 152 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${status}] - branch ${env.BRANCH_NAME}" 145 153 def email_body = """This is an automated email from the Jenkins build machine. It was … … 149 157 150 158 The branch ${env.BRANCH_NAME} has been updated. 159 via ${gitRefOldValue} (commit) 160 from ${gitRefNewValue} (commit) 151 161 152 Check console output at ${env.BUILD_URL} to view the results. """162 Check console output at ${env.BUILD_URL} to view the results. 153 163 154 // def config = new File('/u/cforall/software/cfa/cfa-cc/config').text 155 // def email_to = (config =~ /mailinglist ?= ?(.+)/)[0][1] 164 - Status -------------------------------------------------------------- 165 166 BUILD# ${env.BUILD_NUMBER} - ${status} 167 168 - Log ----------------------------------------------------------------- 169 ${gitLog} 170 ----------------------------------------------------------------------- 171 Summary of changes: 172 ${gitDiff} 173 """ 174 156 175 def email_to = "pabuhr@uwaterloo.ca, rschlunt@uwaterloo.ca, a3moss@uwaterloo.ca, tdelisle@uwaterloo.ca, brice.dobry@huawei.com" 157 176 -
doc/working/resolver_design.md
r2f6b7c9 r685a5e8 87 87 element-wise; summation starts at `(0, 0, 0, 0)`. 88 88 89 **TODO** Costs of T, T*, lvalue T, rvalue T conversions (if applicable) 90 91 ### Lvalue Conversions ### 92 **TODO** Finish me 93 94 #### NOTES 95 * C standard 6.3.2.1 96 * pointer_like_generators.md 97 98 ### Qualifier Conversions ### 99 **TODO** Finish me 100 101 #### NOTES 102 C standard 6.3.2.3.2: We can add any qualifier to the pointed-to-type of a 103 pointer. 104 * Glen thinks this means that we should make the default assignment operator 105 `?=?(T volatile restrict *this, T that)`, but I'm not sure I like the 106 implications for the actual implementation of forcing `this` to be 107 volatile 108 * I want to consider whether this property should generalize to other 109 parameterized types (e.g. `lvalue T`, `box(T)`) 110 111 C standard 6.3.2.1.1: "modifiable lvalues" recursively exclude structs with 112 const-qualified fields 113 114 C standard 6.3.2.1.2: Using lvalues as rvalues implicitly strips qualifiers 115 116 C standard 6.2.4.26: 117 118 C standard 6.7.3: **TODO** 89 ### Lvalue and Qualifier Conversions ### 90 C defines the notion of a _lvalue_, essentially an addressable object, as well 91 as a number of type _qualifiers_, `const`, `volatile`, and `restrict`. 92 As these type qualifiers are generally only meaningful to the type system as 93 applied to lvalues, the two concepts are closely related. 94 A const lvalue cannot be modified, the compiler cannot assume that a volatile 95 lvalue will not be concurrently modified by some other part of the system, and 96 a restrict lvalue must have pointer type, and the compiler may assume that no 97 other pointer in scope aliases that pointer (this is solely a performance 98 optimization, and may be ignored by implementers). 99 _Lvalue-to-rvalue conversion_, which takes an lvalue of type `T` and converts 100 it to an expression result of type `T` (commonly called an _rvalue_ of type 101 `T`) also strips all the qualifiers from the lvalue, as an expression result 102 is a value, not an addressable object that can have properties like 103 immutability. 104 Though lvalue-to-rvalue conversion strips the qualifiers from lvalues, 105 derived rvalue types such as pointer types may include qualifiers; 106 `const int *` is a distinct type from `int *`, though the latter is safely 107 convertable to the former. 108 In general, any number of qualifiers can be safely added to the 109 pointed-to-type of a pointer type, e.g. `int *` converts safely to 110 `const int *` and `volatile int *`, both of which convert safely to 111 `const volatile int *`. 112 113 Since lvalues are precicely "addressable objects", in C, only lvalues can be 114 used as the operand of the `&` address-of operator. 115 Similarly, only modifiable lvalues may be used as the assigned-to 116 operand of the mutating operators: assignment, compound assignment 117 (e.g. `+=`), and increment and decrement; roughly speaking, lvalues without 118 the `const` qualifier are modifiable, but lvalues of incomplete types, array 119 types, and struct or union types with const members are also not modifiable. 120 Lvalues are produced by the following expressions: object identifiers 121 (function identifiers are not considered to be lvalues), the result of the `*` 122 dereference operator applied to an object pointer, the result of a member 123 expression `s.f` if the left argument `s` is an lvalue (note that the 124 preceding two rules imply that the result of indirect member expressions 125 `s->f` are always lvalues, by desugaring to `(*s).f`), and the result of the 126 indexing operator `a[i]` (similarly by its desugaring to `*((a)+(i))`). 127 Somewhat less obviously, parenthesized lvalue expressions, string literals, 128 and compound literals (e.g. `(struct foo){ 'x', 3.14, 42 }`) are also lvalues. 129 130 All of the conversions described above are defined in standard C, but Cforall 131 requires further features from its type system. 132 In particular, to allow overloading of the `*?` and `?[?]` dereferencing and 133 indexing operators, Cforall requires a way to declare that the functions 134 defining these operators return lvalues, and since C functions never return 135 lvalues and for syntactic reasons we wish to distinguish functions which 136 return lvalues from functions which return pointers, this is of necessity an 137 extension to standard C. 138 In the current design, an `lvalue` qualifier can be added to function return 139 types (and only to function return types), the effect of which is to return a 140 pointer which is implicitly dereferenced by the caller. 141 C++ includes the more general concept of _references_, which are typically 142 implemented as implicitly dereferenced pointers as well. 143 Another use case which C++ references support is providing a way to pass 144 function parameters by reference (rather than by value) with a natural 145 syntax; Cforall in its current state has no such mechanism. 146 As an example, consider the following (currently typical) copy-constructor 147 signature and call: 148 149 void ?{}(T *lhs, T rhs); 150 151 T x; 152 T y = { x }; 153 154 Note that the right-hand argument is passed by value, and would in fact be 155 copied twice in the course of the constructor call `T y = { x };` (once into 156 the parameter by C's standard `memcpy` semantics, once again in the body of 157 the copy constructor, though it is possible that return value optimization 158 will elide the `memcpy`-style copy). 159 However, to pass by reference using the existing pointer syntax, the example 160 above would look like this: 161 162 void ?{}(T *lhs, const T *rhs); 163 164 T x; 165 T y = { &x }; 166 167 This example is not even as bad as it could be; assuming pass-by-reference is 168 the desired semantics for the `?+?` operator, that implies the following 169 design today: 170 171 T ?+?(const T *lhs, const T *rhs); 172 173 T a, b; 174 T c = &a + &b, 175 176 In addition to `&a + &b` being unsightly and confusing syntax to add `a` and 177 `b`, it also introduces a possible ambiguity with pointer arithmetic on `T*` 178 which can only be resolved by return-type inference. 179 180 Pass-by-reference and marking functions as returning lvalues instead of the 181 usual rvalues are actually closely related concepts, as obtaining a reference 182 to pass depends on the referenced object being addressable, i.e. an lvalue, 183 and lvalue return types are effectively return-by-reference. 184 Cforall should also unify the concepts, with a parameterized type for 185 "reference to `T`", which I will write `ref T`. 186 Syntax bikeshedding can be done later (there are some examples at the bottom 187 of this section), but `ref T` is sufficiently distinct from both the existing 188 `lvalue T` (which it subsumes) and the closely related C++ `T&` to allow 189 independent discussion of its semantics. 190 191 Firstly, assignment to a function parameter as part of a function call and 192 local variable initialization have almost identical semantics, so should be 193 treated similarly for the reference type too; this implies we should be able 194 to declare local variables of reference type, as in the following: 195 196 int x = 42; 197 ref int r = x; // r is now an alias for x 198 199 Unlike in C++, we would like to have the capability to re-bind references 200 after initialization, as this allows the attractive syntax of references to 201 support some further useful code patterns, such as first initializing a 202 reference after its declaration. 203 Constant references to `T` (`const ref T`) should not be re-bindable. 204 205 One option for re-binding references is to use a dedicated operator, as in the 206 code example below: 207 208 int i = 42, j = 7; 209 ref int r = i; // bind r to i 210 r = j; // set i (== r) to 7 211 r := j; // rebind r to j using the new := rebind operator 212 i = 42; // reset i (!= r) to 42 213 assert( r == 7 ); 214 215 The other syntactic option for reference re-bind would be to overload 216 assignment and use type inference on the left and right-hand sides to 217 determine whether the referred-to variable on the left should be reassigned to 218 the value on the right, or if the reference on the left should be aliased to 219 the reference on the right. 220 This could be disambiguated with casts, as in the following code example: 221 222 int i 223 int j; 224 ref int r = i; // (0a) 225 ref int s = i; // (0b) 226 227 i = j; // (1) 228 i = (int)s; // (2) 229 i = s; // (3) 230 // --------------------- 231 r = s; // (4) 232 r = (ref int)j; // (5) 233 // --------------------- 234 r = j; // (6) 235 r = (int)s; // (7) 236 237 By the expected aliasing syntax, (0a) and (0b) are initializing `r` and `s` as 238 aliases for `i`. 239 For C compatibility, (1) has to be assignment; in general, any assignment to a 240 non-reference type should be assignment, so (2) and (3) are as well. 241 By types, (4) and (5) should have the same semantics, and the semantics of (6) 242 and (7) should match as well. 243 This suggests that (4) and (5) are reference re-bind, and (6) and (7) are an 244 assignment to the referred variable; this makes the syntax to explicitly alias 245 a local variable rather ugly (and inconsistent with the initialization 246 syntax), as well as making it rather awkward to copy the value stored in one 247 reference-type variable into another reference type variable (which is likely 248 more painful in functions with by-reference parameters than with local 249 variables of reference type). 250 251 Because of the aforementioned issues with overloading assignment as reference 252 rebind, in addition to the fact that reference rebind should not be a 253 user-overloadable operator (unlike assignment), I propose refererence rebind 254 should have its own dedicated operator. 255 256 The semantics and restrictions of `ref T` are effectively the semantics of an 257 lvalue of type `T`, and by this analogy there should be a safe, qualifier 258 dropping conversion from `ref const volatile restrict T` (and every other 259 qualifier combination on the `T` in `ref T`) to `T`. 260 With this conversion, the resolver may type most expressions that C would 261 call "lvalue of type `T`" as `ref T`. 262 There's also an obvious argument that lvalues of a (possibly-qualified) type 263 `T` should be convertable to references of type `T`, where `T` is also 264 so-qualified (e.g. lvalue `int` to `ref int`, lvalue `const char` to 265 `ref const char`). 266 By similar arguments to pointer types, qualifiers should be addable to the 267 referred-to type of a reference (e.g. `ref int` to `ref const int`). 268 As a note, since pointer arithmetic is explictly not defined on `ref T`, 269 `restrict ref T` should be allowable and would have alias-analysis rules that 270 are actually comprehensible to mere mortals. 271 272 Using pass-by-reference semantics for function calls should not put syntactic 273 constraints on how the function is called; particularly, temporary values 274 should be able to be passed by reference. 275 The mechanism for this pass-by-reference would be to store the value of the 276 temporary expression into a new unnamed temporary, and pass the reference of 277 that temporary to the function. 278 As an example, the following code should all compile and run: 279 280 void f(ref int x) { printf("%d\n", x++); } 281 282 int i = 7, j = 11; 283 const int answer = 42; 284 285 f(i); // (1) 286 f(42); // (2) 287 f(i + j); // (3) 288 f(answer); // (4) 289 290 The semantics of (1) are just like C++'s, "7" is printed, and `i` has the 291 value 8 afterward. 292 For (2), "42" is printed, and the increment of the unnamed temporary to 43 is 293 not visible to the caller; (3) behaves similarly, printing "19", but not 294 changing `i` or `j`. 295 (4) is a bit of an interesting case; we want to be able to support named 296 constants like `answer` that can be used anywhere the constant expression 297 they're replacing (like `42`) could go; in this sense, (4) and (2) should have 298 the same semantics. 299 However, we don't want the mutation to the `x` parameter to be visible in 300 `answer` afterward, because `answer` is a constant, and thus shouldn't change. 301 The solution to this is to allow chaining of the two `ref` conversions; 302 `answer` has the type `ref const int`, which can be converted to `int` by the 303 lvalue-to-rvalue conversion (which drops the qualifiers), then up to `ref int` 304 by the temporary-producing rvalue-to-lvalue conversion. 305 Thus, an unnamed temporary is inserted, initialized to `answer` (i.e. 42), 306 mutated by `f`, then discarded; "42" is printed, just as in case (2), and 307 `answer` still equals 42 after the call, because it was the temporary that was 308 mutated, not `answer`. 309 It may be somewhat surprising to C++ programmers that `f(i)` mutates `i` while 310 `f(answer)` does not mutate `answer` (though `f(answer)` would be illegal in 311 C++, leading to the dreaded "const hell"), but the behaviour of this rule can 312 be determined by examining local scope with the simple rule "non-`const` 313 references to `const` variables produce temporaries", which aligns with 314 programmer intuition that `const` variables cannot be mutated. 315 316 To bikeshed syntax for `ref T`, there are three basic options: language 317 keywords (`lvalue T` is already in Cforall), compiler-supported "special" 318 generic types (e.g. `ref(T)`), or sigils (`T&` is familiar to C++ 319 programmers). 320 Keyword or generic based approaches run the risk of name conflicts with 321 existing code, while any sigil used would have to be carefully chosen to not 322 create parsing conflicts. 323 324 **TODO** Consider arguments for move semantics and see if there is a 325 compelling case for rvalue references. 119 326 120 327 ### Conversion Operator Costs ### … … 624 831 perfectly legal and has the desired semantics. 625 832 833 We can assert that `T` can be used in a boolean context as follows: 834 835 `forall(otype T | { int ?!=?(T, _zero_t); })` 836 837 Since the C standard (6.5.16.1.1) specifically states that pointers can be 838 assigned into `_Bool` variables (and implies that other artithmetic types can 839 be assigned into `_Bool` variables), it seems natural to say that assignment 840 into a `_Bool` variable effectively constitutes a boolean context. 841 To allow this interpretation, I propose including the following function (or 842 its effective equivalent) in the prelude: 843 844 forall(otype T | { int ?!=?(T, _zero_t); }) 845 void ?{safe}( _Bool *this, T that ) { *this = that != 0; } 846 847 Note that this conversion is not transitive; that is, for `t` a variable of 848 some "truthy" type `T`, `(_Bool)t;` would use this conversion (in the absence 849 of a lower-cost one), `(int)t;` would not use this conversion (and in fact 850 would not be legal in the absence of another valid way to convert a `T` to an 851 `int`), but `(int)(_Bool)t;` could legally use this conversion. 852 626 853 Similarly giving literal `1` the special type `_unit_t` allows for more 627 854 concise and consistent specification of the increment and decrement operators, … … 714 941 then take the non-deleted alternative, and of two equivalent-cost deleted 715 942 interpretations with the same return type pick one arbitrarily rather than 716 producing an ambiguous resolution. 943 producing an ambiguous resolution. This would also be useful for forbidding 944 pointer-to-floating-point explicit conversions (C11, 6.5.4.4). 945 **TODO** Cover default parameters, maybe named parameters (see "named 946 arguments" thread of 11 March 2016) 947 717 948 718 949 ### Sizeof, Alignof & Offsetof Expressions ### … … 732 963 for each interpretation `J` of `y` with the same type as `J` costing the sum 733 964 of the costs of `I` and `J`. 965 966 ### Index Expressions ### 967 **TODO** Consider adding polymorphic function in prelude for this, as per 968 6.5.2.1.2 in the C standard: 969 970 forall(otype T, otype I, otype R, otype E | { R ?+?(T, I); lvalue E *?(R); }) 971 lvalue E ?[?](T a, I i) { return *(a + i); } 972 973 I think this isn't actually a good idea, because the cases for it are niche, 974 mostly odd tricks like `0[p]` as an alternate syntax for dereferencing a 975 pointer `p`, and adding it to the prelude would slow down resolution of 976 every index expression just a bit. Our existing prelude includes an indexing 977 operator `forall(otype T) lvalue T ?[?](ptrdiff_t, T*)`, plus qualified 978 variants, which should satisfy C source-compatibility without propegating this 979 silly desugaring further. 734 980 735 981 #### Compatible Functions ####
Note: See TracChangeset
for help on using the changeset viewer.