Merge pull request #13594 from apple/bugfix_largetype

Merge pull request #13590 from shajrawi/large_type_bugfix_part1
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index db8d946..902bcc7 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -323,19 +323,10 @@
     // The Self type is abstract, so we can fulfill its metadata from
     // the Self metadata parameter.
     addSelfMetadataFulfillment(selfTy);
-  } else {
-    // If the Self type is concrete, we have a witness thunk with a
-    // fully substituted Self type. The witness table parameter is not
-    // used.
-    //
-    // FIXME: As above, we should fulfill the Self metadata and
-    // conformance from our two special paramaters here. However, the
-    // Self metadata will be inexact.
-    //
-    // For now, just fulfill the generic arguments of 'Self'.
-    considerType(selfTy, IsInexact, Sources.size() - 1, MetadataPath());
   }
 
+  considerType(selfTy, IsInexact, Sources.size() - 1, MetadataPath());
+
   // The witness table for the Self : P conformance can be
   // fulfilled from the Self witness table parameter.
   Sources.emplace_back(MetadataSource::Kind::SelfWitnessTable,
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index 1d77564..34e7ba6 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -3759,10 +3759,31 @@
   bool isEntryBlock = (i->getParent() == i->getFunction()->getEntryBlock());
   auto addr =
       type.allocateStack(*this, i->getElementType(), isEntryBlock, dbgname);
-
-  emitDebugInfoForAllocStack(i, type, addr.getAddress().getAddress());
-  
   setLoweredStackAddress(i, addr);
+
+  // Generate Debug Info.
+  if (!Decl)
+    return;
+  emitDebugInfoForAllocStack(i, type, addr.getAddress().getAddress());
+
+  // To make it unambiguous whether a `var` binding has been initialized,
+  // zero-initialize the first pointer-sized field. LLDB uses this to
+  // recognize to detect uninitizialized variables. This can be removed once
+  // swiftc switches to @llvm.dbg.addr() intrinsics. This dead store will get
+  // optimized away when optimizations are enabled.
+  if (!Decl->getType()->getClassOrBoundGenericClass())
+    return;
+
+  auto *AI = dyn_cast<llvm::AllocaInst>(addr.getAddress().getAddress());
+  if (!AI)
+    return;
+
+  auto &DL = IGM.DataLayout;
+  if (DL.getTypeSizeInBits(AI->getAllocatedType()) < DL.getPointerSize())
+    return;
+  auto *BC = Builder.CreateBitCast(AI, IGM.OpaquePtrTy->getPointerTo());
+  Builder.CreateStore(llvm::ConstantPointerNull::get(IGM.OpaquePtrTy), BC,
+                      IGM.getPointerAlignment());
 }
 
 static void
diff --git a/test/DebugInfo/uninitialized.swift b/test/DebugInfo/uninitialized.swift
new file mode 100644
index 0000000..ca3549e
--- /dev/null
+++ b/test/DebugInfo/uninitialized.swift
@@ -0,0 +1,11 @@
+// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s
+class MyClass {}
+
+// CHECK: define {{.*}} @_T013uninitialized1fyyF
+public func f() {
+  var object: MyClass
+  // CHECK: %[[OBJ:.*]] = alloca %[[T:.*]]*, align
+  // CHECK: call void @llvm.dbg.declare(metadata %[[T]]** %[[OBJ]],
+  // CHECK: %[[BC:.*]] = bitcast %[[T]]** %[[OBJ]] to %swift.opaque**, !dbg
+  // CHECK: store %swift.opaque* null, %swift.opaque** %[[BC]], align {{.*}}, !dbg
+}
diff --git a/test/IRGen/witness_method.sil b/test/IRGen/witness_method.sil
index 3669da7..09cd5e3 100644
--- a/test/IRGen/witness_method.sil
+++ b/test/IRGen/witness_method.sil
@@ -110,7 +110,7 @@
   func disrupt() -> GrowthHack
 }
 
-// CHECK-LABEL: define{{( protected)?}} swiftcc void @classArchetypeWitnessMethod(%swift.type* %CoverSheet, %T14witness_method9TPSReportC** noalias nocapture swiftself dereferenceable({{4|8}}), %swift.type* %Self, i8** %SelfWitnessTable)
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @classArchetypeWitnessMethod(%T14witness_method9TPSReportC** noalias nocapture swiftself dereferenceable({{4|8}}), %swift.type* %Self, i8** %SelfWitnessTable)
 
 sil @classArchetypeWitnessMethod : $@convention(witness_method: Strategy) <T><CoverSheet where T : TPSReport<CoverSheet>> (@in_guaranteed T) -> () {
 entry(%self : $*T):
diff --git a/test/Interpreter/protocol_extensions.swift b/test/Interpreter/protocol_extensions.swift
index ab001b7..1b15052 100644
--- a/test/Interpreter/protocol_extensions.swift
+++ b/test/Interpreter/protocol_extensions.swift
@@ -315,6 +315,8 @@
 
 class SelfMetadataDerived : SelfMetadataBase {}
 
+class SelfMetadataGeneric<T> : SelfMetadataTest {}
+
 func testSelfMetadata<T : SelfMetadataTest>(_ x: T, _ t: T.T) -> [Any.Type] {
   return [x.staticTypeOfSelf(),
           x.staticTypeOfSelfTakesT(t),
@@ -348,6 +350,16 @@
     expectTrue(SelfMetadataDerived.self == result[2])
     expectTrue(SelfMetadataDerived.self == result[3])
   }
+
+  // Make sure the calling convention works out if 'Self' is a generic
+  // class too.
+  do {
+    let result = testSelfMetadata(SelfMetadataGeneric<Int>(), 0)
+    expectTrue(SelfMetadataGeneric<Int>.self == result[0])
+    expectTrue(SelfMetadataGeneric<Int>.self == result[1])
+    expectTrue(SelfMetadataGeneric<Int>.self == result[2])
+    expectTrue(SelfMetadataGeneric<Int>.self == result[3])
+  }
 }
 
 runAllTests()