summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2008-06-13 23:01:12 +0000
committerEli Friedman <eli.friedman@gmail.com>2008-06-13 23:01:12 +0000
commit1e692ace08959399794363e77499b73da5494af9 (patch)
treef3b2a525ece7b5a7ad2df5328e1d46db215aef4c
parented6c70f63067ec06757aa019750765b80e23b423 (diff)
downloadclang-1e692ace08959399794363e77499b73da5494af9.tar.gz
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
-rw-r--r--lib/CodeGen/CGBuiltin.cpp1
-rw-r--r--lib/CodeGen/CGDecl.cpp2
-rw-r--r--lib/CodeGen/CGExpr.cpp102
-rw-r--r--lib/CodeGen/CGExprAgg.cpp15
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp5
-rw-r--r--lib/CodeGen/CGStmt.cpp2
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--lib/CodeGen/CodeGenFunction.h34
-rw-r--r--test/CodeGen/volatile.c88
9 files changed, 200 insertions, 51 deletions
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<CallExpr>(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<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 @@ 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<PointerType>(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<llvm::PointerType>(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<InitListExpr>(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<llvm::PointerType>(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<ObjCMethodDecl>(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;
+}