diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index 4e8dacf0..86457f95 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -578,6 +578,7 @@ public: enum BfTypedValueKind { BfTypedValueKind_Addr, + BfTypedValueKind_VolatileAddr, BfTypedValueKind_CopyOnMutateAddr, BfTypedValueKind_CopyOnMutateAddr_Derived, BfTypedValueKind_ReadOnlyAddr, @@ -586,7 +587,7 @@ enum BfTypedValueKind BfTypedValueKind_ReadOnlyTempAddr, BfTypedValueKind_ThisAddr, BfTypedValueKind_BaseAddr, - BfTypedValueKind_ReadOnlyThisAddr, + BfTypedValueKind_ReadOnlyThisAddr, BfTypedValueKind_ReadOnlyBaseAddr, BfTypedValueKind_Value, @@ -750,6 +751,11 @@ public: mKind = (BfTypedValueKind)((int)mKind - 1); } + bool IsVolatile() const + { + return mKind == BfTypedValueKind_VolatileAddr; + } + bool IsSplat() const { return (mKind >= BfTypedValueKind_SplatHead) && (mKind <= BfTypedValueKind_ParamsSplat); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 6654100c..846a7e4f 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -5093,6 +5093,9 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe } } + if ((fieldDef->mIsVolatile) && (retVal.IsAddr())) + retVal.mKind = BfTypedValueKind_VolatileAddr; + if (wantsLoadValue) retVal = mModule->LoadValue(retVal, NULL, mIsVolatileReference); else @@ -5902,8 +5905,8 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr resolvedArg.mResolvedType = argValue.mType; if (resolvedArg.mResolvedType->IsRef()) argValue.mKind = BfTypedValueKind_Value; - else if ((!resolvedArg.mResolvedType->IsStruct()) && (!resolvedArg.mResolvedType->IsSizedArray()) && (!resolvedArg.mResolvedType->IsValuelessType())) - argValue = mModule->LoadValue(argValue, NULL, exprEvaluator.mIsVolatileReference); + if (exprEvaluator.mIsVolatileReference) + resolvedArg.mArgFlags = (BfArgFlags)(resolvedArg.mArgFlags | BfArgFlag_Volatile); } resolvedArg.mUncastedTypedValue = argValue; resolvedArg.mTypedValue = argValue; diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index ca9ce83b..c4e7b825 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -21,7 +21,8 @@ enum BfArgFlags BfArgFlag_UninitializedExpr = 0x400, BfArgFlag_StringInterpolateFormat = 0x800, BfArgFlag_StringInterpolateArg = 0x1000, - BfArgFlag_Cascade = 0x2000 + BfArgFlag_Cascade = 0x2000, + BfArgFlag_Volatile = 0x8000 }; enum BfResolveArgsFlags diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 73de18c0..b72caf73 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -12583,11 +12583,9 @@ BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bo { return BfTypedValue(loadedVal, typedValue.mType, false); } - - /*if (isVolatile) - mBfIRBuilder->CreateFence(BfIRFenceType_AcquireRelease);*/ + PopulateType(typedValue.mType, BfPopulateType_Data); - loadedVal = mBfIRBuilder->CreateAlignedLoad(loadedVal, std::max(1, (int)typedValue.mType->mAlign), isVolatile); + loadedVal = mBfIRBuilder->CreateAlignedLoad(loadedVal, std::max(1, (int)typedValue.mType->mAlign), isVolatile || typedValue.IsVolatile()); } return BfTypedValue(loadedVal, typedValue.mType, false); } @@ -14739,6 +14737,8 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance) if (type->IsValuelessType()) return BfTypedValue(globalValue, type); + if (fieldDef->mIsVolatile) + return BfTypedValue(globalValue, type, BfTypedValueKind_VolatileAddr); return BfTypedValue(globalValue, type, !fieldDef->mIsConst); } diff --git a/IDEHelper/Tests/src/MethodCalls.bf b/IDEHelper/Tests/src/MethodCalls.bf index b2a2a985..ac895b1e 100644 --- a/IDEHelper/Tests/src/MethodCalls.bf +++ b/IDEHelper/Tests/src/MethodCalls.bf @@ -159,6 +159,29 @@ namespace Tests } + + static void InInt(in int a) + { + Test.Assert(a == 123); +#unwarn + int* aPtr = &a; + *aPtr = 234; + } + + static void CopyStructA(StructA sa) + { +#unwarn + StructA* saPtr = &sa; + saPtr.mA += 1000; + } + + static void InStructA(in StructA sa) + { +#unwarn + StructA* saPtr = &sa; + saPtr.mA += 1000; + } + [Test] public static void TestBasics() { @@ -206,6 +229,16 @@ namespace Tests var v = ObjMethod(.. scope String()); Test.Assert(v.GetType() == typeof(String)); + + int b = 123; + InInt(b); + Test.Assert(b == 234); + + StructA sa4 = .(400, 401); + CopyStructA(sa4); + Test.Assert(sa4.mA == 400); + InStructA(sa4); + Test.Assert(sa4.mA == 1400); } } }