diff --git a/svf-llvm/lib/SVFIRBuilder.cpp b/svf-llvm/lib/SVFIRBuilder.cpp
index 0ee96aec3..173ba2f52 100644
--- a/svf-llvm/lib/SVFIRBuilder.cpp
+++ b/svf-llvm/lib/SVFIRBuilder.cpp
@@ -244,6 +244,13 @@ void SVFIRBuilder::initialiseNodes()
             const CallGraphNode* cgn = llvmModuleSet()->getCallGraphNode(func);
             // add value node representing the function
             pag->addFunValNode(cgn, iter->second, icfgNode);
+        } else if (auto argval = SVFUtil::dyn_cast<Argument>(llvmValue)) {
+            pag->addArgValNode(
+                llvmModuleSet()->getCallGraphNode(argval->getParent()),
+                argval->getArgNo(), LLVMUtil::isArgOfUncalledFunction(argval), iter->second,
+                icfgNode);
+            llvmModuleSet()->addToLLVMVal2SVFVarMap(
+                argval, pag->getGNode(iter->second));
         }
         else if (auto fpValue = SVFUtil::dyn_cast<ConstantFP>(llvmValue))
         {
diff --git a/svf/include/Graphs/GenericGraph.h b/svf/include/Graphs/GenericGraph.h
index 790c1330d..8f116b049 100644
--- a/svf/include/Graphs/GenericGraph.h
+++ b/svf/include/Graphs/GenericGraph.h
@@ -154,6 +154,7 @@ class SVFBaseNode
         // ┌── SVFVar: Classes of top-level variables (ValVar) and address-taken variables (ObjVar)
         // │   └── ValVar: Classes of top-level variable nodes
         ValNode,                 // ├──Represents a standard value variable
+        ArgNode,                 // ├──Represents an argument value variable
         FunValNode,              // ├──Represents a Function value variable
         GepValNode,              // ├──Represents a GEP value variable
         RetNode,                 // ├──Represents a return value node
@@ -289,7 +290,7 @@ class SVFBaseNode
 
     static inline bool isSVFVarKind(GNodeK n)
     {
-        static_assert(DummyObjNode - ValNode == 23,
+        static_assert(DummyObjNode - ValNode == 24,
                       "The number of SVFVarKinds has changed, make sure the "
                       "range is correct");
 
@@ -298,7 +299,7 @@ class SVFBaseNode
 
     static inline bool isValVarKinds(GNodeK n)
     {
-        static_assert(DummyValNode - ValNode == 11,
+        static_assert(DummyValNode - ValNode == 12,
                       "The number of ValVarKinds has changed, make sure the "
                       "range is correct");
         return n <= DummyValNode && n >= ValNode;
diff --git a/svf/include/SVFIR/SVFIR.h b/svf/include/SVFIR/SVFIR.h
index a9ab9edab..36970934d 100644
--- a/svf/include/SVFIR/SVFIR.h
+++ b/svf/include/SVFIR/SVFIR.h
@@ -578,6 +578,13 @@ class SVFIR : public IRGraph
         return addValNode(nullptr, node, i);
     }
 
+    NodeID addArgValNode(const CallGraphNode* callGraphNode, u32_t argNo,
+                         bool isUncalled, NodeID i, const ICFGNode* icfgNode) {
+        ArgValVar* node =
+            new ArgValVar(i, callGraphNode, argNo, isUncalled, icfgNode);
+        return addValNode(nullptr, node, i);
+    }
+
     inline NodeID addConstantFPValNode(const SVFValue* curInst, double dval, const NodeID i,
                                        const ICFGNode* icfgNode)
     {
diff --git a/svf/include/SVFIR/SVFVariables.h b/svf/include/SVFIR/SVFVariables.h
index 1cf11ef2d..9f2df3a89 100644
--- a/svf/include/SVFIR/SVFVariables.h
+++ b/svf/include/SVFIR/SVFVariables.h
@@ -133,11 +133,6 @@ class SVFVar : public GenericPAGNodeTy
             {
                 return inst->getParent()->getParent();
             }
-            // For function arguments, return their parent function
-            else if (auto arg = SVFUtil::dyn_cast<SVFArgument>(value))
-            {
-                return arg->getParent();
-            }
         }
 
         // Return nullptr for globals/constants with no parent function
@@ -388,6 +383,82 @@ class ObjVar: public SVFVar
 };
 
 
+/**
+ * @brief Class representing a function argument variable in the SVFIR
+ *
+ * This class models function argument in the program analysis. It extends ValVar
+ * to specifically handle function argument.
+ */
+class ArgValVar: public ValVar {
+    friend class SVFIRWriter;
+    friend class SVFIRReader;
+
+private:
+    const CallGraphNode* cgNode;
+    u32_t argNo;
+    bool uncalled;
+
+protected:
+    /// Constructor to create function argument (for SVFIRReader/deserialization)
+    ArgValVar(NodeID i, PNODEK ty = ArgNode) : ValVar(i, ty) {}
+
+public:
+    ///  Methods for support type inquiry through isa, cast, and dyn_cast:
+    //@{
+    static inline bool classof(const ArgValVar*)
+    {
+        return true;
+    }
+    static inline bool classof(const ValVar* node)
+    {
+        return node->getNodeKind() == ArgNode;
+    }
+    static inline bool classof(const SVFVar* node)
+    {
+        return node->getNodeKind() == ArgNode;
+    }
+    static inline bool classof(const GenericPAGNodeTy* node)
+    {
+        return node->getNodeKind() == ArgNode;
+    }
+    static inline bool classof(const SVFBaseNode* node)
+    {
+        return node->getNodeKind() == ArgNode;
+    }
+    //@}
+
+    /// Constructor
+    ArgValVar(NodeID i, const CallGraphNode* callGraphNode, u32_t argNo,
+              bool isUncalled, const ICFGNode* icn, PNODEK ty = ArgNode);
+
+    /// Return name of a LLVM value
+    inline const std::string getValueName() const
+    {
+        if (value)
+            return value->getName() + " (argument valvar)";
+        return " (argument valvar)";
+    }
+
+    virtual const SVFFunction* getFunction() const;
+
+    const SVFFunction* getParent() const;
+
+    ///  Return the index of this formal argument in its containing function.
+    /// For example in "void foo(int a, float b)" a is 0 and b is 1.
+    inline u32_t getArgNo() const
+    {
+        return argNo;
+    }
+
+    inline bool isArgOfUncalledFunction() const
+    {
+        return uncalled;
+    }
+
+    virtual const std::string toString() const;
+};
+
+
 /*
  * Gep Value (Pointer) variable, this variable can be dynamic generated for field sensitive analysis
  * e.g. memcpy, temp gep value variable needs to be created
diff --git a/svf/include/Util/SVFUtil.h b/svf/include/Util/SVFUtil.h
index 9327def15..437f05f54 100644
--- a/svf/include/Util/SVFUtil.h
+++ b/svf/include/Util/SVFUtil.h
@@ -351,6 +351,8 @@ inline bool isArgOfUncalledFunction(const SVFValue* svfval)
         return false;
 }
 
+bool isArgOfUncalledFunction(const SVFVar* svfvar);
+
 const ObjVar* getObjVarOfValVar(const ValVar* valVar);
 
 /// Return thread fork function
diff --git a/svf/lib/SVFIR/SVFFileSystem.cpp b/svf/lib/SVFIR/SVFFileSystem.cpp
index 7181f58dd..da7dd8681 100644
--- a/svf/lib/SVFIR/SVFFileSystem.cpp
+++ b/svf/lib/SVFIR/SVFFileSystem.cpp
@@ -222,6 +222,7 @@ cJSON* SVFIRWriter::virtToJson(const SVFVar* var)
         CASE(DummyValNode, DummyValVar);
         CASE(DummyObjNode, DummyObjVar);
         CASE(FunObjNode, FunObjVar);
+        CASE(ArgNode, ArgValVar);
         CASE(FunValNode, FunValVar);
         CASE(HeapObjNode, HeapObjVar);
         CASE(StackObjNode, StackObjVar);
diff --git a/svf/lib/SVFIR/SVFIR.cpp b/svf/lib/SVFIR/SVFIR.cpp
index 869b48953..12621c98b 100644
--- a/svf/lib/SVFIR/SVFIR.cpp
+++ b/svf/lib/SVFIR/SVFIR.cpp
@@ -670,11 +670,10 @@ bool SVFIR::isValidPointer(NodeID nodeId) const
 
     if (node->hasValue() && node->isPointer())
     {
-        if(const SVFArgument* arg = SVFUtil::dyn_cast<SVFArgument>(node->getValue()))
-        {
-            if (!(arg->getParent()->isDeclaration()))
-                return true;
-        }
+        if (const ValVar* pVar = pag->getBaseValVar(nodeId))
+            if (const ArgValVar* arg = SVFUtil::dyn_cast<ArgValVar>(pVar))
+                if (!(arg->getParent()->isDeclaration()))
+                    return true;
     }
 
     if ((node->getInEdges().empty() && node->getOutEdges().empty()))
@@ -694,7 +693,7 @@ bool SVFIR::isValidTopLevelPtr(const SVFVar* node)
                 return true;
             }
             else if(node->hasValue())
-                return !SVFUtil::isArgOfUncalledFunction(node->getValue());
+                return !SVFUtil::isArgOfUncalledFunction(node);
         }
     }
     return false;
diff --git a/svf/lib/SVFIR/SVFVariables.cpp b/svf/lib/SVFIR/SVFVariables.cpp
index 4cbb9c9a0..0e109a53f 100644
--- a/svf/lib/SVFIR/SVFVariables.cpp
+++ b/svf/lib/SVFIR/SVFVariables.cpp
@@ -46,6 +46,7 @@ SVFVar::SVFVar(const SVFValue* val, NodeID i, PNODEK k) :
     switch (k)
     {
     case ValNode:
+    case ArgNode:
     case ConstantDataValNode:
     case GlobalValNode:
     case BlackHoleNode:
@@ -144,6 +145,39 @@ const std::string ObjVar::toString() const
     return rawstr.str();
 }
 
+ArgValVar::ArgValVar(SVF::NodeID i, const SVF::CallGraphNode* callGraphNode,
+                     SVF::u32_t argNo, bool isUncalled,
+                     const SVF::ICFGNode* icn, SVF::SVFVar::PNODEK ty)
+    : ValVar(callGraphNode->getFunction()->getArg(argNo), i, ty, icn), cgNode(callGraphNode),
+      argNo(argNo), uncalled(isUncalled)
+{
+    isPtr =
+        callGraphNode->getFunction()->getArg(argNo)->getType()->isPointerTy();
+}
+
+const SVFFunction* ArgValVar::getFunction() const
+{
+    return getParent();
+}
+
+const SVFFunction* ArgValVar::getParent() const
+{
+    return cgNode->getFunction();
+}
+
+const std::string ArgValVar::toString() const
+{
+    std::string str;
+    std::stringstream rawstr(str);
+    rawstr << "ArgValVar ID: " << getId();
+    if (Options::ShowSVFIRValue())
+    {
+        rawstr << "\n";
+        rawstr << valueOnlyToString();
+    }
+    return rawstr.str();
+}
+
 const std::string GepValVar::toString() const
 {
     std::string str;
@@ -468,4 +502,3 @@ bool SVFVar::isConstDataOrAggDataButNotNullPtr() const
     else
         return false;
 }
-
diff --git a/svf/lib/Util/SVFUtil.cpp b/svf/lib/Util/SVFUtil.cpp
index bf3568ec7..08de0becf 100644
--- a/svf/lib/Util/SVFUtil.cpp
+++ b/svf/lib/Util/SVFUtil.cpp
@@ -425,6 +425,14 @@ const SVFFunction* SVFUtil::getProgEntryFunction()
     return nullptr;
 }
 
+bool SVFUtil::isArgOfUncalledFunction(const SVFVar* svfvar)
+{
+    const ValVar* pVar = PAG::getPAG()->getBaseValVar(svfvar->getId());
+    if(const ArgValVar* arg = SVFUtil::dyn_cast<ArgValVar>(pVar))
+        return arg->isArgOfUncalledFunction();
+    else
+        return false;
+}
 
 const ObjVar* SVFUtil::getObjVarOfValVar(const SVF::ValVar* valVar)
 {
diff --git a/svf/lib/Util/ThreadAPI.cpp b/svf/lib/Util/ThreadAPI.cpp
index 2cf335753..2cca866a5 100644
--- a/svf/lib/Util/ThreadAPI.cpp
+++ b/svf/lib/Util/ThreadAPI.cpp
@@ -207,13 +207,13 @@ const SVFVar* ThreadAPI::getLockVal(const ICFGNode *cs) const
 const SVFVar* ThreadAPI::getJoinedThread(const CallICFGNode *cs) const
 {
     assert(isTDJoin(cs) && "not a thread join function!");
-    const SVFVar* join = cs->getArgument(0);
+    const ValVar* join = cs->getArgument(0);
     for(const SVFStmt* stmt : join->getInEdges())
     {
         if(SVFUtil::isa<LoadStmt>(stmt))
             return stmt->getSrcNode();
     }
-    if(SVFUtil::isa<SVFArgument>(join->getValue()))
+    if(SVFUtil::isa<ArgValVar>(join))
         return join;
 
     assert(false && "the value of the first argument at join is not a load instruction?");