From 1e692ace08959399794363e77499b73da5494af9 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Fri, 13 Jun 2008 23:01:12 +0000 Subject: [PATCH] Basic support for volatile loads and stores. Stores the volatile qualifier in the lvalue, and changes lvalue loads/stores to honor the volatile flag. Places which need some further attention are marked with FIXMEs. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Patch by Cédric Venet. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52264 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 1 - lib/CodeGen/CGDecl.cpp | 2 +- lib/CodeGen/CGExpr.cpp | 102 ++++++++++++++++++++------------ lib/CodeGen/CGExprAgg.cpp | 15 ++++- lib/CodeGen/CGObjCGNU.cpp | 5 ++ lib/CodeGen/CGStmt.cpp | 2 +- lib/CodeGen/CodeGenFunction.cpp | 2 + lib/CodeGen/CodeGenFunction.h | 34 ++++++++--- test/CodeGen/volatile.c | 88 +++++++++++++++++++++++++++ 9 files changed, 200 insertions(+), 51 deletions(-) create mode 100644 test/CodeGen/volatile.c diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 232f6d6d4a..51d7ced2d8 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -143,7 +143,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { Value *SrcPtr = CreateTempAlloca(SrcValue->getType(), "dst_ptr"); - // FIXME: Volatile Builder.CreateStore(SrcValue, SrcPtr, false); const llvm::Type *Type = diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index fe58ca05fe..2d30ed5746 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -208,7 +208,7 @@ void CodeGenFunction::EmitParmDecl(const ParmVarDecl &D, llvm::Value *Arg) { AllocaInsertPt); // Store the initial value into the alloca. - Builder.CreateStore(Arg, DeclPtr); + Builder.CreateStore(Arg, DeclPtr,Ty.isVolatileQualified()); } else { // Otherwise, if this is an aggregate, just use the input pointer. DeclPtr = Arg; diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index d960503e57..05a8972a40 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -97,7 +97,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { printf("Statement class: %d\n", E->getStmtClass()); WarnUnsupported(E, "l-value expression"); llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType())); - return LValue::MakeAddr(llvm::UndefValue::get(Ty)); + return LValue::MakeAddr(llvm::UndefValue::get(Ty), + E->getType().getCVRQualifiers()); } case Expr::CallExprClass: return EmitCallExprLValue(cast(E)); @@ -134,7 +135,7 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) { // Simple scalar l-value. if (EltTy->isSingleValueType()) { - llvm::Value *V = Builder.CreateLoad(Ptr, "tmp"); + llvm::Value *V = Builder.CreateLoad(Ptr, LV.isVolatileQualified(),"tmp"); // Bool can have different representation in memory than in registers. if (ExprType->isBooleanType()) { @@ -150,7 +151,8 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) { } if (LV.isVectorElt()) { - llvm::Value *Vec = Builder.CreateLoad(LV.getVectorAddr(), "tmp"); + llvm::Value *Vec = Builder.CreateLoad(LV.getVectorAddr(), + LV.isVolatileQualified(), "tmp"); return RValue::get(Builder.CreateExtractElement(Vec, LV.getVectorIdx(), "vecext")); } @@ -178,7 +180,7 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV, unsigned short BitfieldSize = LV.getBitfieldSize(); unsigned short EndBit = LV.getBitfieldStartBit() + BitfieldSize; - llvm::Value *V = Builder.CreateLoad(Ptr, "tmp"); + llvm::Value *V = Builder.CreateLoad(Ptr, LV.isVolatileQualified(), "tmp"); llvm::Value *ShAmt = llvm::ConstantInt::get(EltTy, EltTySize - EndBit); V = Builder.CreateShl(V, ShAmt, "tmp"); @@ -199,7 +201,8 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV, // shuffle the input or extract/insert them as appropriate. RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV, QualType ExprType) { - llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddr(), "tmp"); + llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddr(), + LV.isVolatileQualified(), "tmp"); const llvm::Constant *Elts = LV.getExtVectorElts(); @@ -258,11 +261,11 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, if (!Dst.isSimple()) { if (Dst.isVectorElt()) { // Read/modify/write the vector, inserting the new element. - // FIXME: Volatility. - llvm::Value *Vec = Builder.CreateLoad(Dst.getVectorAddr(), "tmp"); + llvm::Value *Vec = Builder.CreateLoad(Dst.getVectorAddr(), + Dst.isVolatileQualified(), "tmp"); Vec = Builder.CreateInsertElement(Vec, Src.getScalarVal(), Dst.getVectorIdx(), "vecins"); - Builder.CreateStore(Vec, Dst.getVectorAddr()); + Builder.CreateStore(Vec, Dst.getVectorAddr(),Dst.isVolatileQualified()); return; } @@ -289,7 +292,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, DstAddr = Builder.CreateBitCast(DstAddr, llvm::PointerType::get(SrcTy, AS), "storetmp"); - Builder.CreateStore(Src.getScalarVal(), DstAddr); + Builder.CreateStore(Src.getScalarVal(), DstAddr, Dst.isVolatileQualified()); } void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, @@ -299,7 +302,8 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, llvm::Value *Ptr = Dst.getBitfieldAddr(); llvm::Value *NewVal = Src.getScalarVal(); - llvm::Value *OldVal = Builder.CreateLoad(Ptr, "tmp"); + llvm::Value *OldVal = Builder.CreateLoad(Ptr, Dst.isVolatileQualified(), + "tmp"); // The bitfield type and the normal type differ when the storage sizes // differ (currently just _Bool). @@ -326,7 +330,7 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, // Finally, merge the two together and store it. NewVal = Builder.CreateOr(OldVal, NewVal, "tmp"); - Builder.CreateStore(NewVal, Ptr); + Builder.CreateStore(NewVal, Ptr, Dst.isVolatileQualified()); } void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src, @@ -334,8 +338,8 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src, QualType Ty) { // This access turns into a read/modify/write of the vector. Load the input // value now. - llvm::Value *Vec = Builder.CreateLoad(Dst.getExtVectorAddr(), "tmp"); - // FIXME: Volatility. + llvm::Value *Vec = Builder.CreateLoad(Dst.getExtVectorAddr(), + Dst.isVolatileQualified(), "tmp"); const llvm::Constant *Elts = Dst.getExtVectorElts(); llvm::Value *SrcVal = Src.getScalarVal(); @@ -359,7 +363,7 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src, Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt, "tmp"); } - Builder.CreateStore(Vec, Dst.getExtVectorAddr()); + Builder.CreateStore(Vec, Dst.getExtVectorAddr(), Dst.isVolatileQualified()); } @@ -368,16 +372,19 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { if (VD && (VD->isBlockVarDecl() || isa(VD))) { if (VD->getStorageClass() == VarDecl::Extern) - return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false)); + return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false), + E->getType().getCVRQualifiers()); else { llvm::Value *V = LocalDeclMap[VD]; assert(V && "BlockVarDecl not entered in LocalDeclMap?"); - return LValue::MakeAddr(V); + return LValue::MakeAddr(V, E->getType().getCVRQualifiers()); } } else if (VD && VD->isFileVarDecl()) { - return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false)); + return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false), + E->getType().getCVRQualifiers()); } else if (const FunctionDecl *FD = dyn_cast(E->getDecl())) { - return LValue::MakeAddr(CGM.GetAddrOfFunctionDecl(FD, false)); + return LValue::MakeAddr(CGM.GetAddrOfFunctionDecl(FD, false), + E->getType().getCVRQualifiers()); } assert(0 && "Unimp declref"); //an invalid LValue, but the assert will @@ -393,13 +400,15 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { switch (E->getOpcode()) { default: assert(0 && "Unknown unary operator lvalue!"); case UnaryOperator::Deref: - return LValue::MakeAddr(EmitScalarExpr(E->getSubExpr())); + return LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()), + E->getSubExpr()->getType().getCanonicalType()->getAsPointerType() + ->getPointeeType().getCVRQualifiers()); case UnaryOperator::Real: case UnaryOperator::Imag: LValue LV = EmitLValue(E->getSubExpr()); unsigned Idx = E->getOpcode() == UnaryOperator::Imag; return LValue::MakeAddr(Builder.CreateStructGEP(LV.getAddress(), - Idx, "idx")); + Idx, "idx"),E->getSubExpr()->getType().getCVRQualifiers()); } } @@ -415,7 +424,7 @@ LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) { uint64_t RealLen = CAT->getSize().getZExtValue(); StringLiteral.resize(RealLen, '\0'); - return LValue::MakeAddr(CGM.GetAddrOfConstantString(StringLiteral)); + return LValue::MakeAddr(CGM.GetAddrOfConstantString(StringLiteral),0); } LValue CodeGenFunction::EmitPreDefinedLValue(const PreDefinedExpr *E) { @@ -452,7 +461,7 @@ LValue CodeGenFunction::EmitPreDefinedLValue(const PreDefinedExpr *E) { C = new llvm::GlobalVariable(C->getType(), true, llvm::GlobalValue::InternalLinkage, C, GlobalVarName, CurFn->getParent()); - return LValue::MakeAddr(C); + return LValue::MakeAddr(C,0); } LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { @@ -461,12 +470,13 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { // If the base is a vector type, then we are forming a vector element lvalue // with this subscript. - if (E->getLHS()->getType()->isVectorType()) { + if (E->getBase()->getType()->isVectorType()) { // Emit the vector as an lvalue to get its address. - LValue LHS = EmitLValue(E->getLHS()); + LValue LHS = EmitLValue(E->getBase()); assert(LHS.isSimple() && "Can only subscript lvalue vectors here!"); // FIXME: This should properly sign/zero/extend or truncate Idx to i32. - return LValue::MakeVectorElt(LHS.getAddress(), Idx); + return LValue::MakeVectorElt(LHS.getAddress(), Idx, + E->getBase()->getType().getCVRQualifiers()); } // The base must be a pointer, which is not an aggregate. Emit it. @@ -484,7 +494,9 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { // size is a VLA. if (!E->getType()->isConstantSizeType()) assert(0 && "VLA idx not implemented"); - return LValue::MakeAddr(Builder.CreateGEP(Base, Idx, "arrayidx")); + return LValue::MakeAddr(Builder.CreateGEP(Base, Idx, "arrayidx"), + E->getBase()->getType().getCanonicalType()->getAsPointerType() + ->getPointeeType().getCVRQualifiers()); } static @@ -508,7 +520,8 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { if (Base.isSimple()) { llvm::Constant *CV = GenerateConstantVector(Indices); - return LValue::MakeExtVectorElt(Base.getAddress(), CV); + return LValue::MakeExtVectorElt(Base.getAddress(), CV, + E->getBase()->getType().getCVRQualifiers()); } assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!"); @@ -522,14 +535,16 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { CElts.push_back(BaseElts->getOperand(Indices[i])); } llvm::Constant *CV = llvm::ConstantVector::get(&CElts[0], CElts.size()); - return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), CV); + return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), CV, + E->getBase()->getType().getCVRQualifiers()); } LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { bool isUnion = false; Expr *BaseExpr = E->getBase(); llvm::Value *BaseValue = NULL; - + unsigned CVRQualifiers=0; + // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar. if (E->isArrow()) { BaseValue = EmitScalarExpr(BaseExpr); @@ -537,6 +552,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { cast(BaseExpr->getType().getCanonicalType()); if (PTy->getPointeeType()->isUnionType()) isUnion = true; + CVRQualifiers = PTy->getPointeeType().getCVRQualifiers(); } else { LValue BaseLV = EmitLValue(BaseExpr); @@ -544,15 +560,17 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { BaseValue = BaseLV.getAddress(); if (BaseExpr->getType()->isUnionType()) isUnion = true; + CVRQualifiers = BaseExpr->getType().getCVRQualifiers(); } FieldDecl *Field = E->getMemberDecl(); - return EmitLValueForField(BaseValue, Field, isUnion); + return EmitLValueForField(BaseValue, Field, isUnion, CVRQualifiers); } LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue, FieldDecl* Field, - bool isUnion) + bool isUnion, + unsigned CVRQualifiers) { llvm::Value *V; unsigned idx = CGM.getTypes().getLLVMFieldNo(Field); @@ -574,14 +592,16 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue, CodeGenTypes::BitFieldInfo bitFieldInfo = CGM.getTypes().getBitFieldInfo(Field); return LValue::MakeBitfield(V, bitFieldInfo.Begin, bitFieldInfo.Size, - Field->getType()->isSignedIntegerType()); + Field->getType()->isSignedIntegerType(), + Field->getType().getCVRQualifiers()|CVRQualifiers); } V = Builder.CreateStructGEP(BaseValue, idx, "tmp"); // Match union field type. if (isUnion) { - const llvm::Type *FieldTy = CGM.getTypes().ConvertTypeForMem(Field->getType()); + const llvm::Type *FieldTy = + CGM.getTypes().ConvertTypeForMem(Field->getType()); const llvm::PointerType * BaseTy = cast(BaseValue->getType()); unsigned AS = BaseTy->getAddressSpace(); @@ -590,15 +610,17 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue, "tmp"); } - return LValue::MakeAddr(V); + return LValue::MakeAddr(V, + Field->getType().getCVRQualifiers()|CVRQualifiers); } -LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E) { +LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E) +{ const llvm::Type *LTy = ConvertType(E->getType()); llvm::Value *DeclPtr = CreateTempAlloca(LTy, ".compoundliteral"); const Expr* InitExpr = E->getInitializer(); - LValue Result = LValue::MakeAddr(DeclPtr); + LValue Result = LValue::MakeAddr(DeclPtr, E->getType().getCVRQualifiers()); if (E->getType()->isComplexType()) { EmitComplexExprIntoAddr(InitExpr, DeclPtr, false); @@ -640,7 +662,9 @@ RValue CodeGenFunction::EmitCallExpr(Expr *FnExpr, Expr *const *Args, LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) { // Can only get l-value for call expression returning aggregate type RValue RV = EmitCallExpr(E); - return LValue::MakeAddr(RV.getAggregateAddr()); + // FIXME: can this be volatile? + return LValue::MakeAddr(RV.getAggregateAddr(), + E->getType().getCVRQualifiers()); } LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) { @@ -665,14 +689,16 @@ LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) { // Get object pointer and coerce object pointer to correct type. llvm::Value *Object = EmitLValue(E->getBase()).getAddress(); + // FIXME: Volatility Object = Builder.CreateLoad(Object, E->getDecl()->getName()); if (Object->getType() != ObjectType) Object = Builder.CreateBitCast(Object, ObjectType); // Return a pointer to the right element. + // FIXME: volatile return LValue::MakeAddr(Builder.CreateStructGEP(Object, Index, - Decl->getName())); + Decl->getName()),0); } RValue CodeGenFunction::EmitCallExpr(llvm::Value *Callee, QualType FnType, diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 80231ccb80..924a5cf46d 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -280,6 +280,7 @@ void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { llvm::Value *ArgValue = CGF.EmitLValue(VE->getSubExpr()).getAddress(); llvm::Value *V = Builder.CreateVAArg(ArgValue, CGF.ConvertType(VE->getType())); if (DestPtr) + // FIXME: volatility Builder.CreateStore(V, DestPtr); } @@ -299,6 +300,7 @@ void AggExprEmitter::EmitNonConstInit(InitListExpr *E) { if (isa(Init)) CGF.EmitAggExpr(Init, NextVal, VolatileDest); else + // FIXME: volatility Builder.CreateStore(CGF.EmitScalarExpr(Init), NextVal); } @@ -309,6 +311,7 @@ void AggExprEmitter::EmitNonConstInit(InitListExpr *E) { for (/*Do not initialize i*/; i < NumArrayElements; ++i) { llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array"); if (EType->isSingleValueType()) + // FIXME: volatility Builder.CreateStore(llvm::Constant::getNullValue(EType), NextVal); else EmitAggregateClear(NextVal, QType); @@ -333,6 +336,7 @@ void AggExprEmitter::EmitNullInitializationToLValue(LValue LV, QualType T) { // For non-aggregates, we can store zero const llvm::Type *T = cast(LV.getAddress()->getType())->getElementType(); + // FIXME: volatility Builder.CreateStore(llvm::Constant::getNullValue(T), LV.getAddress()); } else { // Otherwise, just memset the whole thing to zero. This is legal @@ -382,12 +386,16 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { uint64_t NumArrayElements = AType->getNumElements(); QualType ElementType = E->getType()->getAsArrayType()->getElementType(); + unsigned CVRqualifier = E->getType().getCanonicalType()->getAsArrayType() + ->getElementType().getCVRQualifiers(); + for (uint64_t i = 0; i != NumArrayElements; ++i) { llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array"); if (i < NumInitElements) - EmitInitializationToLValue(E->getInit(i), LValue::MakeAddr(NextVal)); + EmitInitializationToLValue(E->getInit(i), + LValue::MakeAddr(NextVal, CVRqualifier)); else - EmitNullInitializationToLValue(LValue::MakeAddr(NextVal), + EmitNullInitializationToLValue(LValue::MakeAddr(NextVal, CVRqualifier), ElementType); } return; @@ -418,7 +426,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // Initializers can't initialize unnamed fields, e.g. "int : 20;" continue; } - LValue FieldLoc = CGF.EmitLValueForField(DestPtr, CurField, isUnion); + // FIXME: volatility + LValue FieldLoc = CGF.EmitLValueForField(DestPtr, CurField, isUnion,0); if (CurInitVal < NumInitElements) { // Store the initializer into the field // This will probably have to get a bit smarter when we support diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 78e02e409a..e545fc12ee 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -222,6 +222,7 @@ llvm::Value *CGObjCGNU::GetSelector(llvm::IRBuilder &Builder, if (SelTypes == 0) { // If it's already cached, return it. if (UntypedSelectors[CName->getStringValue()]) { + // FIXME: Volatility return Builder.CreateLoad(UntypedSelectors[CName->getStringValue()]); } // If it isn't, cache it. @@ -230,6 +231,7 @@ llvm::Value *CGObjCGNU::GetSelector(llvm::IRBuilder &Builder, llvm::GlobalValue::InternalLinkage, ".objc_untyped_selector_alias", NULL, &TheModule); UntypedSelectors[CName->getStringValue()] = Sel; + // FIXME: Volatility return Builder.CreateLoad(Sel); } // Typed selectors @@ -238,6 +240,7 @@ llvm::Value *CGObjCGNU::GetSelector(llvm::IRBuilder &Builder, CTypes->getStringValue()); // If it's already cached, return it. if (TypedSelectors[Selector]) { + // FIXME: Volatility return Builder.CreateLoad(TypedSelectors[Selector]); } // If it isn't, cache it. @@ -246,6 +249,7 @@ llvm::Value *CGObjCGNU::GetSelector(llvm::IRBuilder &Builder, llvm::GlobalValue::InternalLinkage, ".objc_typed_selector_alias", NULL, &TheModule); TypedSelectors[Selector] = Sel; + // FIXME: Volatility return Builder.CreateLoad(Sel); } } @@ -337,6 +341,7 @@ llvm::Value *CGObjCGNU::GenerateMessageSendSuper(llvm::IRBuilder &Builder, llvm::StructType *ObjCSuperTy = llvm::StructType::get(Receiver->getType(), IdTy, NULL); llvm::Value *ObjCSuper = Builder.CreateAlloca(ObjCSuperTy); + // FIXME: volatility Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0)); Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1)); diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 067d6ebd09..736fad0d2e 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -808,6 +808,6 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { llvm::InlineAsm::get(FTy, AsmString, Constraints, S.isVolatile() || S.getNumOutputs() == 0); llvm::Value *Result = Builder.CreateCall(IA, Args.begin(), Args.end(), ""); - if (ResultAddr) + if (ResultAddr) // FIXME: volatility Builder.CreateStore(Result, ResultAddr); } diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 1557738ed1..c8ef8fcd33 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -114,6 +114,7 @@ void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { AllocaInsertPt); // Store the initial value into the alloca. + // FIXME: volatility Builder.CreateStore(AI, DeclPtr); DMEntry = DeclPtr; ++AI; ++AI; @@ -152,6 +153,7 @@ llvm::Value *CodeGenFunction::LoadObjCSelf(void) { if(const ObjCMethodDecl *OMD = dyn_cast(CurFuncDecl)) { llvm::Value *SelfPtr = LocalDeclMap[&(*OMD->getSelfDecl())]; + // FIXME: Volatility return Builder.CreateLoad(SelfPtr, "self"); } return NULL; diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 077a7bdbdc..313d2d1829 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -149,8 +149,7 @@ public: /// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a /// bitrange. class LValue { - // FIXME: Volatility. Restrict? - // alignment? + // FIXME: alignment? enum { Simple, // This is a normal l-value, use getAddress(). @@ -174,12 +173,26 @@ class LValue { bool IsSigned; } BitfieldData; // BitField start bit and size }; + + bool Volatile:1; + // FIXME: set but never used, what effect should it have? + bool Restrict:1; + +private: + static void SetQualifiers(unsigned Qualifiers, LValue& R) { + R.Volatile = (Qualifiers&QualType::Volatile)!=0; + R.Restrict = (Qualifiers&QualType::Restrict)!=0; + } + public: bool isSimple() const { return LVType == Simple; } bool isVectorElt() const { return LVType == VectorElt; } bool isBitfield() const { return LVType == BitField; } bool isExtVectorElt() const { return LVType == ExtVectorElt; } + bool isVolatileQualified() const { return Volatile; } + bool isRestrictQualified() const { return Restrict; } + // simple lvalue llvm::Value *getAddress() const { assert(isSimple()); return V; } // vector elt lvalue @@ -206,37 +219,44 @@ public: return BitfieldData.IsSigned; } - static LValue MakeAddr(llvm::Value *V) { + static LValue MakeAddr(llvm::Value *V, unsigned Qualifiers) { LValue R; R.LVType = Simple; R.V = V; + SetQualifiers(Qualifiers,R); return R; } - static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx) { + static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx, + unsigned Qualifiers) { LValue R; R.LVType = VectorElt; R.V = Vec; R.VectorIdx = Idx; + SetQualifiers(Qualifiers,R); return R; } - static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts) { + static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts, + unsigned Qualifiers) { LValue R; R.LVType = ExtVectorElt; R.V = Vec; R.VectorElts = Elts; + SetQualifiers(Qualifiers,R); return R; } static LValue MakeBitfield(llvm::Value *V, unsigned short StartBit, - unsigned short Size, bool IsSigned) { + unsigned short Size, bool IsSigned, + unsigned Qualifiers) { LValue R; R.LVType = BitField; R.V = V; R.BitfieldData.StartBit = StartBit; R.BitfieldData.Size = Size; R.BitfieldData.IsSigned = IsSigned; + SetQualifiers(Qualifiers,R); return R; } }; @@ -440,7 +460,7 @@ public: LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E); LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field, - bool isUnion); + bool isUnion, unsigned CVRQualifiers); LValue EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E); //===--------------------------------------------------------------------===// diff --git a/test/CodeGen/volatile.c b/test/CodeGen/volatile.c new file mode 100644 index 0000000000..4db4a5d843 --- /dev/null +++ b/test/CodeGen/volatile.c @@ -0,0 +1,88 @@ +// RUN: clang -emit-llvm < %s | grep volatile | count 26 + +// The number 26 comes from the current codegen for volatile loads; +// if this number changes, it's not necessarily something wrong, but +// something has changed to affect volatile load/store codegen + +int S; +volatile int vS; + +int* pS; +volatile int* pvS; + +int A[10]; +volatile int vA[10]; + +struct { int x; } F; +struct { volatile int x; } vF; + +struct { int x; } F2; +volatile struct { int x; } vF2; +volatile struct { int x; } *vpF2; + +struct { struct { int y; } x; } F3; +volatile struct { struct { int y; } x; } vF3; + +struct { int x:3; } BF; +struct { volatile int x:3; } vBF; + +typedef int v4si __attribute__ ((vector_size (16))); +v4si V; +volatile v4si vV; + +typedef __attribute__(( ext_vector_type(4) )) int extv4; +extv4 VE; +volatile extv4 vVE; + +volatile struct {int x;} aggFct(void); + +void main() { + int i; + + // load + i=S; + i=vS; + i=*pS; + i=*pvS; + i=A[2]; + i=vA[2]; + i=F.x; + i=vF.x; + i=F2.x; + i=vF2.x; + i=vpF2->x; + i=F3.x.y; + i=vF3.x.y; + i=BF.x; + i=vBF.x; + i=V[3]; + i=vV[3]; + i=VE.yx[1]; + i=vVE.zy[1]; + i = aggFct().x; + + + // store + S=i; + vS=i; + *pS=i; + *pvS=i; + A[2]=i; + vA[2]=i; + F.x=i; + vF.x=i; + F2.x=i; + vF2.x=i; + vpF2->x=i; + vF3.x.y=i; + BF.x=i; + vBF.x=i; // FIXME: This generates an extra volatile load + V[3]=i; + vV[3]=i; + + // other ops: + ++S; + ++vS; + i+=S; + i+=vS; +} -- 2.40.0