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.
Patch by Cédric Venet.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52264 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index d960503..05a8972 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -97,7 +97,8 @@
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<CallExpr>(E));
@@ -134,7 +135,7 @@
// 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 @@
}
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt, "tmp");
}
- Builder.CreateStore(Vec, Dst.getExtVectorAddr());
+ Builder.CreateStore(Vec, Dst.getExtVectorAddr(), Dst.isVolatileQualified());
}
@@ -368,16 +372,19 @@
if (VD && (VD->isBlockVarDecl() || isa<ParmVarDecl>(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<FunctionDecl>(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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
cast<PointerType>(BaseExpr->getType().getCanonicalType());
if (PTy->getPointeeType()->isUnionType())
isUnion = true;
+ CVRQualifiers = PTy->getPointeeType().getCVRQualifiers();
}
else {
LValue BaseLV = EmitLValue(BaseExpr);
@@ -544,15 +560,17 @@
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 @@
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<llvm::PointerType>(BaseValue->getType());
unsigned AS = BaseTy->getAddressSpace();
@@ -590,15 +610,17 @@
"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 @@
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 @@
// 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,