]> granicus.if.org Git - clang/commitdiff
Pretty up the emission of field l-values and use volatile and TBAA when
authorJohn McCall <rjmccall@apple.com>
Sat, 26 Feb 2011 08:07:02 +0000 (08:07 +0000)
committerJohn McCall <rjmccall@apple.com>
Sat, 26 Feb 2011 08:07:02 +0000 (08:07 +0000)
loading references as part of that.  Use 'char' TBAA when accessing
(immediate!) fields of a may_alias struct;  fixes PR9307.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126540 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExpr.cpp
lib/CodeGen/CodeGenModule.h
test/CodeGen/may-alias.c
test/CodeGenCXX/anonymous-union-member-initializer.cpp

index 5d69aad42fff563e01ae205ed092faa92f58300c..2abaadff4b6d681aef6a6a76668b943dd30ca887 100644 (file)
@@ -1610,39 +1610,67 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
   }
 }
 
-LValue CodeGenFunction::EmitLValueForField(llvm::Value *BaseValue,
-                                           const FieldDecl *Field,
-                                           unsigned CVRQualifiers) {
-  if (Field->isBitField())
-    return EmitLValueForBitfield(BaseValue, Field, CVRQualifiers);
-
-  const CGRecordLayout &RL =
-    CGM.getTypes().getCGRecordLayout(Field->getParent());
-  unsigned idx = RL.getLLVMFieldNo(Field);
-  llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx, "tmp");
+LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
+                                           const FieldDecl *field,
+                                           unsigned cvr) {
+  if (field->isBitField())
+    return EmitLValueForBitfield(baseAddr, field, cvr);
+
+  const RecordDecl *rec = field->getParent();
+  QualType type = field->getType();
+
+  bool mayAlias = rec->hasAttr<MayAliasAttr>();
+
+  llvm::Value *addr;
+  if (rec->isUnion()) {
+    // For unions, we just cast to the appropriate type.
+    assert(!type->isReferenceType() && "union has reference member");
+
+    const llvm::Type *llvmType = CGM.getTypes().ConvertTypeForMem(type);
+    unsigned AS =
+      cast<llvm::PointerType>(baseAddr->getType())->getAddressSpace();
+    addr = Builder.CreateBitCast(baseAddr, llvmType->getPointerTo(AS),
+                                 field->getName());
+  } else {
+    // For structs, we GEP to the field that the record layout suggests.
+    unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
+    addr = Builder.CreateStructGEP(baseAddr, idx, field->getName());
+
+    // If this is a reference field, load the reference right now.
+    if (const ReferenceType *refType = type->getAs<ReferenceType>()) {
+      llvm::LoadInst *load = Builder.CreateLoad(addr, "ref");
+      if (cvr & Qualifiers::Volatile) load->setVolatile(true);
+
+      if (CGM.shouldUseTBAA()) {
+        llvm::MDNode *tbaa;
+        if (mayAlias)
+          tbaa = CGM.getTBAAInfo(getContext().CharTy);
+        else
+          tbaa = CGM.getTBAAInfo(type);
+        CGM.DecorateInstruction(load, tbaa);
+      }
 
-  // Match union field type.
-  if (Field->getParent()->isUnion()) {
-    const llvm::Type *FieldTy =
-      CGM.getTypes().ConvertTypeForMem(Field->getType());
-    const llvm::PointerType *BaseTy =
-      cast<llvm::PointerType>(BaseValue->getType());
-    unsigned AS = BaseTy->getAddressSpace();
-    V = Builder.CreateBitCast(V,
-                              llvm::PointerType::get(FieldTy, AS),
-                              "tmp");
+      addr = load;
+      mayAlias = false;
+      type = refType->getPointeeType();
+      cvr = 0; // qualifiers don't recursively apply to referencee
+    }
   }
-  if (Field->getType()->isReferenceType())
-    V = Builder.CreateLoad(V, "tmp");
 
-  unsigned Alignment = getContext().getDeclAlign(Field).getQuantity();
-  LValue LV = MakeAddrLValue(V, Field->getType(), Alignment);
-  LV.getQuals().addCVRQualifiers(CVRQualifiers);
+  unsigned alignment = getContext().getDeclAlign(field).getQuantity();
+  LValue LV = MakeAddrLValue(addr, type, alignment);
+  LV.getQuals().addCVRQualifiers(cvr);
 
   // __weak attribute on a field is ignored.
   if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)
     LV.getQuals().removeObjCGCAttr();
-  
+
+  // Fields of may_alias structs act like 'char' for TBAA purposes.
+  // FIXME: this should get propagated down through anonymous structs
+  // and unions.
+  if (mayAlias && LV.getTBAAInfo())
+    LV.setTBAAInfo(CGM.getTBAAInfo(getContext().CharTy));
+
   return LV;
 }
 
index 1528e4b4a84ca4b813800fbe247a3d38ee81fa56..73e6ece14732d30a935ab560abae1df8dd82ba06 100644 (file)
@@ -295,6 +295,8 @@ public:
   const TargetCodeGenInfo &getTargetCodeGenInfo();
   bool isTargetDarwin() const;
 
+  bool shouldUseTBAA() const { return TBAA != 0; }
+
   llvm::MDNode *getTBAAInfo(QualType QTy);
 
   static void DecorateInstruction(llvm::Instruction *Inst,
index f3ea792da36c2c3b26689500a19bedb803fea7cb..6171be763dc7ff32da334db9eb8b5b05b26e8270 100644 (file)
@@ -8,12 +8,21 @@ typedef int __attribute__((may_alias)) aliasing_int;
 
 void test0(aliasing_int *ai, int *i)
 {
+// CHECK: store i32 0, i32* %{{.*}}, !tbaa !1
   *ai = 0;
+// CHECK: store i32 1, i32* %{{.*}}, !tbaa !3
   *i = 1;
 }
 
-// CHECK: store i32 0, i32* %{{.*}}, !tbaa !1
-// CHECK: store i32 1, i32* %{{.*}}, !tbaa !3
+// PR9307
+struct Test1 { int x; };
+struct Test1MA { int x; } __attribute__((may_alias));
+void test1(struct Test1MA *p1, struct Test1 *p2) {
+  // CHECK: store i32 2, i32* {{%.*}}, !tbaa !1
+  p1->x = 2;
+  // CHECK: store i32 3, i32* {{%.*}}, !tbaa !3
+  p2->x = 3;
+}
 
 // CHECK: !0 = metadata !{metadata !"any pointer", metadata !1}
 // CHECK: !1 = metadata !{metadata !"omnipotent char", metadata !2}
index d97a2ae366b31943e5fead6bdaa02c667c7074c9..85e931b50c9144d1e89f72efffe55a0a2f0c0897 100644 (file)
@@ -84,11 +84,11 @@ namespace test3 {
   // CHECK: define void @_ZN5test31AC2Ev(
   // CHECK: [[THIS:%.*]] = load
   // CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0
-  // CHECK-NEXT: [[STRUCT:%.*]] = getelementptr inbounds {{.*}} [[UNION]], i32 0, i32 0
+  // CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to 
   // CHECK-NEXT: [[CALLBACK:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 0
   // CHECK-NEXT: store void (i8*)* null, void (i8*)** [[CALLBACK]]
   // CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0
-  // CHECK-NEXT: [[STRUCT:%.*]] = getelementptr inbounds {{.*}} [[UNION]], i32 0, i32 0
+  // CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to 
   // CHECK-NEXT: [[CVALUE:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 1
   // CHECK-NEXT: store i8* null, i8** [[CVALUE]]
 }