Commit Graph

156 Commits

Author SHA1 Message Date
Michael Gottesman
631f9326ab [PM] Change enum => enum class everywhere in the PM code. Additionally fix some typos.
Swift SVN r13507
2014-02-05 21:25:15 +00:00
Nadav Rotem
1df8e93bbb Convert the diagnostic methods into passes.
Swift SVN r13503
2014-02-05 20:30:49 +00:00
Joe Groff
71379f5bad SILGen: Explicitly mark uninitialized locals with mark_uninitialized, and have DI only consider mark_uninitialized storage.
Have SILGen mark all variables bound from pattern bindings without initializers (and *only* ones without initializers) with mark_uninitialized [var] pseudo instructions. On the DI end, *only* consider mark_uninitialized instructions for DI analysis. This has many benefits:

- DI doesn't waste time analyzing locals that are trivially initialized in the original source code.
- DI doesn't try to mangle canonical SIL that has been inlined from transparent functions, which may have been optimized into a form DI isn't written to understand.

While we're here, fix an issue with DCE where it would try to kill unused MarkUninitialized instructions. Although MarkUninitialized has no side effects, it still is semantically important to raw SIL, and can't be killed.

Chris did most of the work here; I just finished updating tests and fixing bugs.

Swift SVN r13247
2014-01-31 22:50:21 +00:00
Joe Groff
1f5fd1366c DefiniteInit: Assert that DI doesn't mess with copy_addrs that are already [initialization].
We should only be applying the [initialization] attribute to ambivalent copy_addrs from raw SIL.

Swift SVN r13187
2014-01-31 00:31:12 +00:00
Nadav Rotem
a07aed9d1f Change errs() -> dbgs() in a few files.
Swift SVN r12572
2014-01-20 06:36:50 +00:00
Joe Groff
0776c4b6b8 SIL: Reorient function type lowering toward interface types.
Lower types for SILDeclRefs from the interface types of their referents, dragging the old type along for the ride so we can still offer the context to clients that haven't been weaned off of it. Make SILFunctionType's interface types and generic signature independent arguments of its  Derive the context types of SILFunctionType from the interface types, instead of the other way around. Do a bunch of annoying inseparable work in the AST and IRGen to accommodate the switchover.

Swift SVN r12536
2014-01-18 19:42:02 +00:00
Jordan Rose
11008f0ed1 Split diagnostics out into separate files.
Thanks to the way we've set up our diagnostics engine, there's not actually
a reason for /everything/ to get rebuilt when /one/ diagnostic changes.
I've split them up into five categories for now: Parse, Sema, SIL, IRGen,
and Frontend, plus a set of "Common" diagnostics that are used in multiple
areas of the compiler. We can massage this later.

No functionality change, but should speed up compile times!

Swift SVN r12438
2014-01-17 00:15:12 +00:00
Doug Gregor
c6b880a9b7 Definite initialization for initializers relying on a separate ivar initializer.
When we decide to emit a separate ivar initializer method (via the
Objective-C entry point -.cxx_construct), we no longer initialize the
ivars within the initializer. This only happens for derived classes,
so teach DI about uninitialized 'self' values that require a
super.init call but don't require the ivars to be initialized.



Swift SVN r12240
2014-01-13 19:41:16 +00:00
Chris Lattner
22545ffe1f Stop treating escape points as definitions for liveness purposes. While it
is a cute microoptimization (given that escape points *must* be live at their
point in the CFG), it leads to worse diagnostic QoI.



Swift SVN r11985
2014-01-07 06:20:36 +00:00
Chris Lattner
95d05b6b2f emit a custom diagnostics from DI when some path forgets to call self.init
in a delegating initializer.


Swift SVN r11984
2014-01-07 06:13:38 +00:00
Chris Lattner
408011ae59 Implement silgen and DI support for delegating initializers
in value types.


Swift SVN r11982
2014-01-07 06:04:59 +00:00
Chris Lattner
3a970678a1 implement definite initialization enforcement for delegating class
initializers.


Swift SVN r11980
2014-01-07 05:31:33 +00:00
Chris Lattner
40d8536d20 fix a nasty iterator invalidation problem exposed by a patch
Joe is working on.


Swift SVN r11820
2014-01-02 18:37:02 +00:00
Chris Lattner
6fc4d292d6 don't verify each function twice in DI anymore now that DI is stabilized.
If someone passes -debug to the compiler, we still do the check.


Swift SVN r11732
2013-12-30 06:44:33 +00:00
Chris Lattner
23564a20b8 special case a diagnostic to produce a more sensible message when using
Builtin.addressof on an uninitialized variable.   Before:

t.swift:12:26: error: variable 'self.z' captured by a closure before being initialized
    p = UnsafePointer<Y>(Builtin.addressof(&z))
                         ^

After:

t.swift:12:26: error: address of variable 'self.z' taken before it is initialized
    p = UnsafePointer<Y>(Builtin.addressof(&z))
                         ^

This resolves rdar://15699057.



Swift SVN r11482
2013-12-19 21:32:15 +00:00
Chris Lattner
7c41f9e2d7 more diagnostic QoI improvements, refer to properties, not ivars.
Swift SVN r11094
2013-12-10 21:29:04 +00:00
Chris Lattner
7ee082c542 rework general accesses to self to be modeled as full loads, instead of as escapes,
and simplify some code.  The notable aspect of this change is that it improves 
diagnostics for method calls before super.init.



Swift SVN r11081
2013-12-10 17:51:09 +00:00
Chris Lattner
4b24b7f567 Two more QoI improvements to DI diagnostics. For enums,
diagnose failure to initialize with:
  "return from enum initializer method without storing to 'self'"
instead of:
  "variable 'self' used before being initialized"

For partially initialized super.init() calls, emit:
  "super.init not called on all paths leading to use of base object 'SomeClass'"
instead of:
  "use of base object 'SomeClass' before super.init call to initializes it on some paths"

... which didn't make any sense.



Swift SVN r11075
2013-12-10 04:52:56 +00:00
Chris Lattner
12db3b2880 Implement support for validating super.init invariants.
This builds on the infrastructure we have for liveness tracking, by tracking
the "super.init'd" state as another faux memory object that has a liveness.
Each escape/base class use requires super.init to have happened, and super.init
requires super.init to NOT have happened.  This gives us pretty great QoI,
full fidelity to the model, and is pretty simple.

This implements:
<rdar://problem/15579247> We need to validate super.init() invariants in initializers




Swift SVN r11073
2013-12-10 04:15:29 +00:00
Chris Lattner
3c03c0b5e4 rework emitOptionalToRef to use an optional code sequence to get a null class
reference, eliminating the last thing that creates a SIL builtin zero.


Swift SVN r11051
2013-12-09 23:37:51 +00:00
Chris Lattner
7c64fc4a60 remove some dead code: this eliminates the scan of an initializer body
that attempted to detect whether there was an explicit init in the body.
DI takes care of this now.  It also removes the logic for generating code
to default init ivars.


Swift SVN r11044
2013-12-09 23:04:29 +00:00
Chris Lattner
18ae5c62fa Improve the diagnostic for root classes that fail to initialize something. The location
of this diagnostic still doesn't make sense (pointing the the { of the function) but that
is tracked by rdar://15581664.

t.swift:4:3: error: instance variable 'self.x' not initialized at end of initializer
  init() {
  ^




Swift SVN r11042
2013-12-09 22:27:21 +00:00
Chris Lattner
99a3e68b32 don't emit a bogus "variable defined here" diagnostic for 'self'
related diagnostics.


Swift SVN r11037
2013-12-09 21:51:25 +00:00
Chris Lattner
8a5d66dc9d Start improving "DI for init methods" diagnostics. New additions:
t.swift:10:5: error: instance variable 'self.y' not initialized at super.init call
    super.init()
    ^
<unknown>:0: note: variable defined here
t.swift:15:5: error: use of base object 'SomeClass' before super.init call initializes it
    x = 17 
    ^

instead of:

variable 'self.y' captured by a closure before being initialized

for each of them.  <unknown> is in the crosshairs next.



Swift SVN r11036
2013-12-09 21:37:39 +00:00
Chris Lattner
0566ebd40b Fix a bug in in our tuple-element dataflow propagation, where
global "partial liveness" would overwrite local "always live"ness.
Always liveness on a local level always makes a value live-out,
even if it is partially live in.


Swift SVN r11005
2013-12-09 05:44:09 +00:00
Chris Lattner
aed29b4e92 When r10841 turned on DI for struct init methods, it started SILGen generating
new mark_unitialized instructions.  These defeated the alloc_box to stack promotion
pass, so everything ended up on the heap, leading to really terrible performance.
This updates things to understand mark_uninitialized, allowing us to promote them.

This fixes rdar://15607469.


Swift SVN r10985
2013-12-07 23:38:09 +00:00
Michael Gottesman
4379283013 Remove inclusion of SILPasses/Passes.h into Subsystems.h and update all relevant files.
Swift SVN r10880
2013-12-05 19:58:21 +00:00
Chris Lattner
15be357ee1 when DI is reporting an error about a multi-element access,
indicate the first element that is undefined, not the first
element being accessed.  In the example, passing the tuple
inout uses both elements, but the first element is initialized,
so we should complain about t2.1 being uninitialized, not t2.0


Swift SVN r10822
2013-12-05 00:01:21 +00:00
Chris Lattner
51acb02bfb Element analysis applies to more than just tuple elements now,
just refer to them as elements of the memory object, not as 
tuple elements.


Swift SVN r10813
2013-12-04 23:22:14 +00:00
Chris Lattner
5a878c2185 Move tuple flattening functions into DIMemoryObjectInfo
now that they fit there.


Swift SVN r10782
2013-12-04 17:27:47 +00:00
Chris Lattner
6fdb5f9ce1 introduce a new abstraction for handling the memory object being
analyzed, and use it as common currency between the element use
collector and its clients.  Element collection is about to become
more nuanced.  NFC.


Swift SVN r10781
2013-12-04 17:07:29 +00:00
Chris Lattner
3289b6e455 Start emitting "mark_unitialized [rootself]" for the self argument of
enum ctors, and add minimal updates to DI to tolerate this.  Doing so 
exposed a bug that would cause DI to crash handling conditional 
destruction of mark_unintialized (which was never possible
before since globals aren't destructed).



Swift SVN r10778
2013-12-04 06:13:35 +00:00
Chris Lattner
8640266bf7 remove the RemoveDeadAddressingInstructions helper, in favor of
the more fully featured "recursivelyDeleteTriviallyDeadInstructions".


Swift SVN r10724
2013-12-02 01:47:53 +00:00
Chris Lattner
d2adddd34c Now that memopt is its own SIL pass, split it out to its own file. Now
the file sizes are more reasonable and better structured.


Swift SVN r10722
2013-12-02 01:40:21 +00:00
Chris Lattner
dadc9fc6d1 split predictable memory optimization (load promotion + alloc deletion) out to
its own SIL pass.  The bulk of this patch is updating the DI testcase to detangle
DI tests from load promotion tests.



Swift SVN r10721
2013-12-02 01:33:29 +00:00
Chris Lattner
78e5e9879e move the ElementUseCollector out of DefiniteInitialization.cpp
Swift SVN r10720
2013-12-02 01:04:56 +00:00
Chris Lattner
92594b9b5a DI is over 3000 lines of code now, and should be split into two
separate passes.  Start splitting some utility functions out,
and rearranging code a bit.  While I'm at it, rename some bits
to make more sense now that their purpose has settled.


Swift SVN r10719
2013-12-02 00:55:08 +00:00
Chris Lattner
78dd42e10c more minor cleanups, things are settled now.
Swift SVN r10706
2013-12-01 06:29:39 +00:00
Chris Lattner
722436cdc6 the main liveness analysis loop doesn't need escape analysis, the
load promotion pass doesn't need anything more than a set of blocks
that have local definitions.  Simplify code.


Swift SVN r10705
2013-12-01 06:27:30 +00:00
Chris Lattner
f36e720f64 The AllocOptimize phase doesn't need a full LiveOutBlockState, make do with a single bool instead.
Swift SVN r10703
2013-12-01 06:19:24 +00:00
Chris Lattner
b8d628d073 ingloriously fix the serious DI problem:
<rdar://problem/15511392> DI cannot promote loads until the initialization semantics of an entire function is known

This splits load (+destroy_addr) promotion out to a separate pass that
happens after the DI properties of an entire function are known, resolving
the problem.

The upshot is that with this fix, DI is now feature complete (and correct!) for 
all known local and global variable situations (just leaving initializers to do).

The downshot is that some cleanup is required, because this is a purely mechanical
change to the previous algorithms.



Swift SVN r10702
2013-12-01 06:11:55 +00:00
Chris Lattner
dc9e21ed89 implement support for conditional destruction of tuple elements.
a testcase like this:

func test(cond : Bool) {
  var x : (SomeClass, SomeClass)

  if cond {
    x.0 = getSomeClass()
  } else {
    x.1 = getSomeClass() 
  }
}

now ends up with an epilog to destroy "x" that looks like this:

  %1 = builtin_function_ref "lshr_Int2" : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %37
  %2 = builtin_function_ref "trunc_Int2_Int1" : $@thin @callee_owned (Builtin.Int2) -> Builtin.Int1 // users: %38, %31
...
  %30 = load %4#1 : $*Builtin.Int2                // users: %37, %31
  %31 = apply %2(%30) : $@thin @callee_owned (Builtin.Int2) -> Builtin.Int1 // user: %32
  cond_br %31, bb4, bb5                           // id: %32

bb4:                                              // Preds: bb3
  %33 = tuple_element_addr %7#1 : $*(SomeClass, SomeClass), 0 // user: %34
  destroy_addr %33 : $*SomeClass                  // id: %34
  br bb5                                          // id: %35

bb5:                                              // Preds: bb3 bb4
  %36 = integer_literal $Builtin.Int2, 1          // user: %37
  %37 = apply %1(%30, %36) : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %38
  %38 = apply %2(%37) : $@thin @callee_owned (Builtin.Int2) -> Builtin.Int1 // user: %39
  cond_br %38, bb6, bb7                           // id: %39

bb6:                                              // Preds: bb5
  %40 = tuple_element_addr %7#1 : $*(SomeClass, SomeClass), 1 // user: %41
  destroy_addr %40 : $*SomeClass                  // id: %41
  br bb7                                          // id: %42

bb7:                                              // Preds: bb5 bb6
  dealloc_stack %7#0 : $*@local_storage (SomeClass, SomeClass) // id: %43





Swift SVN r10701
2013-12-01 05:22:05 +00:00
Chris Lattner
b84fd18419 implement support for full conditional init/assign processing of tuple elements,
generating the appropriate shifting and or'ing of bits in our liveness mask to
treat each tuple element separately.  This allows us to compile something like:

func test(cond : Bool) {
  var x : (SomeClass, SomeClass)

  if cond {
    x.0 = getSomeClass()
  } else {
    x.1 = getSomeClass() 
  }

  x.0 = getSomeClass()
  x.1 = x.0
}

into:

sil @_T1t4testFT4condSb_T_ : $@thin (Bool) -> () {
bb0(%0 : $Bool):
  %1 = builtin_function_ref "or_Int2" : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // users: %40, %24, %15, %57
  %2 = alloc_stack $Builtin.Int2  // var x        // users: %41, %39, %25, %23, %16, %14, %58, %56, %45, %31, %7, %64
  %3 = alloc_stack $Bool  // var cond             // users: %62, %4
  store %0 to %3#1 : $*Bool                       // id: %4
  %5 = alloc_stack $(SomeClass, SomeClass)  // var x // users: %52, %35, %61, %60, %12, %21, %30, %43, %44
  %6 = integer_literal $Builtin.Int2, 0           // user: %7
  store %6 to %2#1 : $*Builtin.Int2               // id: %7
  %8 = struct_extract %0 : $Bool, #value          // user: %9
  cond_br %8, bb1, bb2                            // id: %9

bb1:                                              // Preds: bb0
  // function_ref t.getSomeClass () -> t.SomeClass
  %10 = function_ref @_T1t12getSomeClassFT_CS_9SomeClass : $@thin () -> @owned SomeClass // user: %11
  %11 = apply %10() : $@thin () -> @owned SomeClass // user: %17
  %12 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 0 // user: %17
  %13 = integer_literal $Builtin.Int2, 1          // user: %15
  %14 = load %2#1 : $*Builtin.Int2                // user: %15
  %15 = apply %1(%14, %13) : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %16
  store %15 to %2#1 : $*Builtin.Int2              // id: %16
  store %11 to %12 : $*SomeClass                  // id: %17
  br bb3                                          // id: %18

bb2:                                              // Preds: bb0
  // function_ref t.getSomeClass () -> t.SomeClass
  %19 = function_ref @_T1t12getSomeClassFT_CS_9SomeClass : $@thin () -> @owned SomeClass // user: %20
  %20 = apply %19() : $@thin () -> @owned SomeClass // user: %26
  %21 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 1 // user: %26
  %22 = integer_literal $Builtin.Int2, -2         // user: %24
  %23 = load %2#1 : $*Builtin.Int2                // user: %24
  %24 = apply %1(%23, %22) : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %25
  store %24 to %2#1 : $*Builtin.Int2              // id: %25
  store %20 to %21 : $*SomeClass                  // id: %26
  br bb3                                          // id: %27

bb3:                                              // Preds: bb2 bb1
  // function_ref t.getSomeClass () -> t.SomeClass
  %28 = function_ref @_T1t12getSomeClassFT_CS_9SomeClass : $@thin () -> @owned SomeClass // user: %29
  %29 = apply %28() : $@thin () -> @owned SomeClass // user: %42
  %30 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 0 // user: %42
  %31 = load %2#1 : $*Builtin.Int2                // user: %33
  %32 = builtin_function_ref "trunc_Int2_Int1" : $@thin @callee_owned (Builtin.Int2) -> Builtin.Int1 // user: %33
  %33 = apply %32(%31) : $@thin @callee_owned (Builtin.Int2) -> Builtin.Int1 // user: %34
  cond_br %33, bb4, bb5                           // id: %34

bb4:                                              // Preds: bb3
  %35 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 0 // user: %36
  destroy_addr %35 : $*SomeClass                  // id: %36
  br bb5                                          // id: %37

bb5:                                              // Preds: bb3 bb4
  %38 = integer_literal $Builtin.Int2, 1          // user: %40
  %39 = load %2#1 : $*Builtin.Int2                // user: %40
  %40 = apply %1(%39, %38) : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %41
  store %40 to %2#1 : $*Builtin.Int2              // id: %41
  store %29 to %30 : $*SomeClass                  // id: %42
  %43 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 0 // user: %59
  %44 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 1 // user: %59
  %45 = load %2#1 : $*Builtin.Int2                // user: %48
  %46 = builtin_function_ref "lshr_Int2" : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %48
  %47 = integer_literal $Builtin.Int2, 1          // user: %48
  %48 = apply %46(%45, %47) : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %50
  %49 = builtin_function_ref "trunc_Int2_Int1" : $@thin @callee_owned (Builtin.Int2) -> Builtin.Int1 // user: %50
  %50 = apply %49(%48) : $@thin @callee_owned (Builtin.Int2) -> Builtin.Int1 // user: %51
  cond_br %50, bb6, bb7                           // id: %51

bb6:                                              // Preds: bb5
  %52 = tuple_element_addr %5#1 : $*(SomeClass, SomeClass), 1 // user: %53
  destroy_addr %52 : $*SomeClass                  // id: %53
  br bb7                                          // id: %54

bb7:                                              // Preds: bb5 bb6
  %55 = integer_literal $Builtin.Int2, -2         // user: %57
  %56 = load %2#1 : $*Builtin.Int2                // user: %57
  %57 = apply %1(%56, %55) : $@thin @callee_owned (Builtin.Int2, Builtin.Int2) -> Builtin.Int2 // user: %58
  store %57 to %2#1 : $*Builtin.Int2              // id: %58
  copy_addr %43 to [initialization] %44 : $*SomeClass // id: %59
  destroy_addr %5#1 : $*(SomeClass, SomeClass)    // id: %60
  dealloc_stack %5#0 : $*@local_storage (SomeClass, SomeClass) // id: %61
  dealloc_stack %3#0 : $*@local_storage Bool      // id: %62
  %63 = tuple ()                                  // user: %65
  dealloc_stack %2#0 : $*@local_storage Builtin.Int2 // id: %64
  return %63 : $()                                // id: %65
}

Which ends up producing this LLVM IR at -O3:

define void @_T1t4testFT4condSb_T_(i1) #0 {
entry:
  %1 = tail call noalias %swift.refcounted* @swift_allocObject(...
  %2 = tail call noalias %swift.refcounted* @swift_allocObject(...
  tail call void @swift_release(%swift.refcounted* %2) #0
  tail call void @swift_release(%swift.refcounted* %1) #0
  ret void
}



Swift SVN r10700
2013-12-01 05:10:48 +00:00
Chris Lattner
f0f997a391 rework the conditional init/assign algorithm to generate destroy_addrs instead
of generating a CFG diamond with a copy of the store (in init and assign forms)
on each arm.  This generalizes to operations that touch multiple tuple elements
better.


Swift SVN r10698
2013-12-01 02:40:01 +00:00
Chris Lattner
1a612b6d13 rewrite the logic to handle conditional destroys to use the same control variable
as is used by conditional inits.  This allows some simplifications and sharing
of concepts, and makes sure that we emit at most one control variable for each
memory object being DI'd.


Swift SVN r10688
2013-11-30 00:19:35 +00:00
Chris Lattner
583d93fd3d Implement support for DI emitting conditional control variable that tracks the
liveness of a memory object throughout the flow graph.  This implements support
for conditional liveness (e.g. the testcase) of general types, but top level
tuples are not handled properly yet.  This is progress to implementing 
rdar://15530750.


Swift SVN r10687
2013-11-29 23:38:29 +00:00
Chris Lattner
b312116ee9 adopt IsInitialization_t in LowerAssignInstruction,
and inline handleInconsistentInitOrAssign into its
caller, since it will remain simple.  Also, add an
assert to make sure the handleStoreUse covers all 
instructions possible in it.  NFC.


Swift SVN r10685
2013-11-29 16:57:57 +00:00
Chris Lattner
eeb1b16830 now that things are rearranged to our liking, introduce a new function
to handle stores that are either an assign or an init, depending on the
control flow leading to them.  This case needs to have a diamond inserted
in the CFG in the general case.  For now, we whitelist trivial types,
since init and assign are the same for them.  This fixes rdar://15530750
for trivial types.


Swift SVN r10684
2013-11-29 07:09:35 +00:00
Chris Lattner
4a50ba45e3 further improve classification: coming out of silgen, we don't know if
anything is a proper reassignment: we only know that it could be either
InitOrAssign or Init.  Classify stores as such, and then have DI classify
things into Assign when it is clearly an overwrite.  This allows later
iterations to avoid reanalyzing generated instructions and allows more
precise reasoning about ambiguous initializations.



Swift SVN r10683
2013-11-29 06:44:15 +00:00
Chris Lattner
8e1b68e4e8 refactor a "InsertCFGDiamond" function out of the conditional destroy logic. NFC.
Swift SVN r10682
2013-11-28 21:28:31 +00:00