|
Static Value-Flow Analysis
|
#include <SVFIRBuilder.h>
Private Types | |
| using | AggregateField = std::vector< unsigned > |
| using | AggregateFieldKey = std::pair< const Value *, AggregateField > |
| Identify a field by its LLVM value and path, rather than by its type alone. | |
| using | AggregateReturnFields = Map< const Function *, std::set< AggregateField > > |
| Field paths extracted from each callee's returned aggregate. | |
Private Member Functions | |
| bool | getAggregateFieldOperands (const AggregateFieldKey &field, std::vector< AggregateFieldKey > &operands) |
| Describe one field definition without emitting any SVFIR statements. | |
| bool | getAggregateFieldNode (const Value *aggregate, const AggregateField &indices, NodeID &node) |
| void | addExtractedFieldCopy (Instruction &inst) |
| void | initialiseAggregateReturns () |
| AggregateReturnFields | discoverAggregateReturnFields () |
| void | createAggregateReturnParams (const Function *fun, const std::set< AggregateField > &fields, const SVFType *pointerType) |
| void | createAggregateCallSlots (const Function *fun, const SVFType *pointerType) |
| void | addAggregateCallFields (const CallInst *call) |
| void | addAggregateReturnStores (ReturnInst &inst) |
| LLVMModuleSet * | llvmModuleSet () |
Static Private Member Functions | |
| static std::optional< AggregateFieldKey > | getExtractedField (const Instruction &inst) |
| Decode a pointer extraction; unsupported instructions have no field. | |
Private Attributes | |
| SVFIR * | pag |
| const SVFBasicBlock * | curBB |
| Current basic block during SVFIR construction when visiting the module. | |
| const Value * | curVal |
| Current Value during SVFIR construction when visiting the module. | |
| Map< AggregateFieldKey, NodeID > | aggregateFieldNodes |
| Reuse the same scalar SVFIR node for repeated requests for a field. | |
| Map< const Function *, std::map< AggregateField, NodeID > > | aggregateReturnParams |
| Output parameters of each modeled callee, in field-path order. | |
| Map< const CallInst *, std::map< AggregateField, NodeID > > | aggregateCallArgs |
Friends | |
| class | GraphDBSVFIRBuilder |
SVFIR Builder to create SVF variables and statements and PAG
Definition at line 49 of file SVFIRBuilder.h.
|
private |
Zero-based indices through nested structs, arrays or fixed vector lanes. For {i32, {ptr, ptr}}, {1, 0} selects the first pointer in the inner struct. An empty path denotes a scalar pointer leaf during dependency traversal.
Definition at line 62 of file SVFIRBuilder.h.
|
private |
Identify a field by its LLVM value and path, rather than by its type alone.
Definition at line 64 of file SVFIRBuilder.h.
|
private |
Field paths extracted from each callee's returned aggregate.
Definition at line 138 of file SVFIRBuilder.h.
|
inline |
Constructor.
Definition at line 153 of file SVFIRBuilder.h.
|
inlinevirtual |
Add Address edge.
Definition at line 406 of file SVFIRBuilder.h.
|
inlineprotected |
Add Address edge from ext call with args like "%5 = call i8* @malloc(i64 noundef 5)".
Definition at line 428 of file SVFIRBuilder.h.
|
inlineprotected |
Add Address edge from allocinst with arraysize like "%4 = alloca i8, i64 3".
Definition at line 417 of file SVFIRBuilder.h.
Append the slot addresses of call as actual output arguments and pass each to the callee's output parameter. createAggregateCallSlots has already created the slots, their addresses and the snapshot loads.
Definition at line 1731 of file SVFIRBuilder.cpp.
|
private |
Store shared field nodes into the callee's output parameters. An unsupported field gets its own fallback; supported siblings keep their shared definitions.
Definition at line 1749 of file SVFIRBuilder.cpp.
|
inlineprotected |
Add Copy edge.
Definition at line 541 of file SVFIRBuilder.h.
|
inlineprotected |
Definition at line 399 of file SVFIRBuilder.h.
|
inlineprotected |
Add Branch statement.
Definition at line 553 of file SVFIRBuilder.h.
|
inlineprotected |
Add Call edge.
Definition at line 577 of file SVFIRBuilder.h.
|
inlineprotected |
Add Copy edge.
Definition at line 535 of file SVFIRBuilder.h.
|
protectedvirtual |
Add the load/store constraints and temp. nodes for the complex constraint *D = *S (where D/S may point to structs).
If sz is 0, we will add edges for all fields.
Definition at line 318 of file SVFIRExtAPI.cpp.
|
inlineprotected |
Definition at line 474 of file SVFIRBuilder.h.
| void SVF::SVFIRBuilder::addEdge | ( | NodeID | src, |
| NodeID | dst, | ||
| SVFStmt::PEDGEK | kind, | ||
| APOffset | offset = 0, |
||
| Instruction * | cs = nullptr |
||
| ) |
|
private |
Copy an extracted pointer from its shared field definition. Unsupported fields keep the existing black-hole fallback.
Definition at line 1797 of file SVFIRBuilder.cpp.
|
inlineprotected |
Add Gep edge.
Definition at line 589 of file SVFIRBuilder.h.
|
inlineprotected |
Add global black hole Address edge.
Definition at line 372 of file SVFIRBuilder.h.
Add Load edge.
Definition at line 559 of file SVFIRBuilder.h.
|
inlineprotected |
Add Offset(Gep) edge.
Definition at line 595 of file SVFIRBuilder.h.
|
inlineprotected |
Add NullPtr PAGNode.
Definition at line 382 of file SVFIRBuilder.h.
|
inlineprotected |
Add Copy edge.
If we already added this phi node, then skip this adding
Definition at line 522 of file SVFIRBuilder.h.
|
inlineprotected |
Add Return edge.
Definition at line 583 of file SVFIRBuilder.h.
|
inlineprotected |
Add SelectStmt.
Definition at line 529 of file SVFIRBuilder.h.
Add Store edge.
Definition at line 565 of file SVFIRBuilder.h.
|
inlineprotected |
Add Thread fork edge for parameter passing.
Definition at line 607 of file SVFIRBuilder.h.
|
inlineprotected |
Add Thread join edge for parameter passing.
Definition at line 613 of file SVFIRBuilder.h.
Add Unary edge.
Definition at line 547 of file SVFIRBuilder.h.
|
inlineprotected |
Add Variant(Gep) edge.
Definition at line 601 of file SVFIRBuilder.h.
|
virtual |
Start building SVFIR here.
Start building SVFIR here
build icfg
initial external library information initial SVFIR nodes
initial SVFIR edges: // handle globals
build callgraph
handle functions
collect return node of function fun
Return SVFIR node will not be created for function which can not reach the return instruction due to call to abort(), exit(), etc. In 176.gcc of SPEC 2000, function build_objc_string() from c-lang.c shows an example when fun.doesNotReturn() evaluates to TRUE because of abort().
To be noted, we do not record arguments which are in declared function without body TODO: what about external functions with SVFIR imported by commandline?
Definition at line 55 of file SVFIRBuilder.cpp.
|
protected |
Compute offset of a gep instruction or gep constant expression.
Return the object node offset according to GEP insn (V). Given a gep edge p = q + i, if "i" is a constant then we return its offset size otherwise if "i" is a variable determined by runtime, then it is a variant offset Return TRUE if the offset of this GEP insn is a constant.
Definition at line 636 of file SVFIRBuilder.cpp.
|
private |
At every call to fun, create a slot, its address and its snapshot for each output parameter (obj, A and V in the aggregate return example). The address is defined at the call, and the snapshot is loaded at the instruction after the call.
Definition at line 1670 of file SVFIRBuilder.cpp.
|
private |
Add one output parameter to fun for each demanded field, in field-path order (out_obj in the aggregate return example). The LLVM signature does not change.
Definition at line 1645 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::createFunObjVars | ( | ) |
set fun in bb
Definition at line 334 of file SVFIRBuilder.cpp.
|
private |
Find the fields of each callee's returned aggregate that callers extract, such as field {0} of make in the aggregate return example. Paths that getAggregateFieldOperands cannot follow are skipped; getAggregateFieldNode later decides which extracted fields are modeled.
Definition at line 1599 of file SVFIRBuilder.cpp.
|
protected |
Get a base SVFVar given a pointer Return the source node of its connected normal gep edge Otherwise return the node id itself s32_t offset : gep offset
if this node is already a base node
Definition at line 2471 of file SVFIRBuilder.cpp.
|
private |
Return the node for (aggregate, indices), reusing cached fields. Unsupported dependencies return false without changing SVFIR or node.
Here, the field node for (a, {0}) copies p; x copies that node: define ptr @field(ptr p) { a = insertvalue { ptr } poison, ptr p, 0 x = extractvalue { ptr } a, 0 ret ptr x }
Definition at line 1479 of file SVFIRBuilder.cpp.
|
private |
Describe one field definition without emitting any SVFIR statements.
Definition at line 1378 of file SVFIRBuilder.cpp.
|
protectedvirtual |
Handle external call.
Find the base type and the max possible offset of an object pointed to by (V).
use user-specified size for this copy operation if the size is a constaint int
MaxFieldLimit == 0 denotes field-insensitive analysis, not an empty memory model. The lower bound of one keeps a representative AccessPath; using zero would drop the memcpy/memset effect entirely.
Unsound scalability trade-off: AccessPaths beyond MaxFieldLimit are omitted, so their external-memory effects are not represented in the SVFIR.
Definition at line 273 of file SVFIRExtAPI.cpp.
Get the base value of (i8* src and i8* dst) for external argument (e.g. memcpy(i8* dst, i8* src, int size))
Example 1:
%0 = getelementptr inbounds struct.outer, struct.inner base, i32 0, i32 0 call void @llvm.memcpy(ptr inner, ptr %0, i64 24, i1 false) The base value for %0 is base. Note: the base is recognized as the base value if the offset (field index) is 0
Example 2: https://github.com/SVF-tools/SVF/issues/1650 https://github.com/SVF-tools/SVF/pull/1652
@i1 = dso_local global struct.inner { i32 0, ptr @f1, ptr @f2 } @n1 = dso_local global struct.outer { i32 0, ptr @i1 }
inner = alloca struct.inner %0 = load ptr, ptr getelementptr inbounds (struct.outer, ptr @n1, i32 0, i32 1) call void @llvm.memcpy(ptr inner, ptr %0, i64 24, i1 false)
The base value for %0 is @i1
Example 3:
@conststruct = internal global <{ [40 x i8], [4 x i8], [4 x i8], [2512 x i8] }> <{ [40 x i8] undef, [4 x i8] zeroinitializer, [4 x i8] undef, [2512 x i8] zeroinitializer }>, align 8
%0 = load ptr, ptr getelementptr inbounds (<{ [40 x i8], [4 x i8], [4 x i8], [2512 x i8] }>, ptr @conststruct, i64 0, i32 0, i64 16)
The base value for %0 is still %0
Definition at line 2098 of file SVFIRBuilder.cpp.
|
inlineprotected |
Definition at line 484 of file SVFIRBuilder.h.
|
inlineprotected |
Definition at line 366 of file SVFIRBuilder.h.
Definition at line 362 of file SVFIRBuilder.h.
|
protected |
Definition at line 2341 of file SVFIRBuilder.cpp.
|
staticprivate |
Decode a pointer extraction; unsupported instructions have no field.
Get the aggregate and field path that a pointer extractvalue, or a pointer extractelement with a constant index, reads. For example, x = extractvalue {ptr, ptr} a, 0 reads field {0} of a.
Definition at line 1773 of file SVFIRBuilder.cpp.
|
protected |
Add a temp field value node according to base value and offset this node is after the initial node method, it is out of scope of symInfo table
Definition at line 2293 of file SVFIRBuilder.cpp.
|
protected |
Get the field of the global variable node FIXME:Here we only get the field that actually used in the program We ignore the initialization of global variable field that not used in the program
if we did not find the constant expression in the program, then we need to create a gep node for this field
Definition at line 880 of file SVFIRBuilder.cpp.
GetObject - Return the object node (stack/global/heap/function) according to a LLVM Value.
Definition at line 203 of file SVFIRBuilder.h.
|
inline |
getReturnNode - Return the node representing the unique return value of a function.
Definition at line 209 of file SVFIRBuilder.h.
Get different kinds of node.
Definition at line 193 of file SVFIRBuilder.h.
getVarargNode - Return the node representing the unique variadic argument of a function.
Definition at line 215 of file SVFIRBuilder.h.
Handle direct call.
Add the constraints for a direct, non-external call.
FIXME: this assertion should be placed for correct checking except bug program like 188.ammp, 300.twolf
Definition at line 2003 of file SVFIRBuilder.cpp.
pthread_create has 1 arg. apr_thread_create has 2 arg.
Connect actual parameter to formal parameter of the start routine
handle indirect calls at pthread create APIs e.g., pthread_create(&t1, nullptr, fp, ...); const Value* fun = ThreadAPI::getThreadAPI()->getForkedFun(inst); if(!SVFUtilisa<Function>(fun)) pag->addIndirectCallsites(cs,pag->getValueNode(fun));
If forkedFun does not pass to spawnee as function type but as void pointer remember to update inter-procedural callgraph/SVFIR/SVFG etc. when indirect call targets are resolved We don't connect the callgraph here, further investigation is need to handle mod-ref during SVFG construction.
TODO: inter-procedural SVFIR edges for thread joins
Definition at line 471 of file SVFIRExtAPI.cpp.
|
protected |
Handle indirect call.
Indirect call is resolved on-the-fly during pointer analysis
Definition at line 2224 of file SVFIRBuilder.cpp.
|
protectedvirtual |
Definition at line 415 of file SVFIRExtAPI.cpp.
|
protected |
Infer field index from byteoffset.
Definition at line 625 of file SVFIRBuilder.cpp.
Definition at line 262 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::initFunObjVar | ( | ) |
Function
set realDefFun for all functions
Definition at line 191 of file SVFIRBuilder.cpp.
|
protected |
src should not point to anything yet
Definition at line 907 of file SVFIRBuilder.cpp.
|
private |
Discover demanded fields and preallocate output parameters, slots and snapshots before visiting instructions. See the aggregate return example in SVFIRBuilder.h.
Definition at line 1577 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::initialiseBaseObjVars | ( | ) |
Definition at line 376 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::initialiseNodes | ( | ) |
Initialize nodes and edges.
add address edges for constant nodes.
add argvalvar for svffunctions
Definition at line 535 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::initialiseValVars | ( | ) |
Definition at line 453 of file SVFIRBuilder.cpp.
set exit block: exit basic block must have no successors and have a return instruction
Definition at line 219 of file SVFIRBuilder.cpp.
|
inlineprivate |
Definition at line 623 of file SVFIRBuilder.h.
Process constant expression.
Handle constant expression, and connect the gep edge
Definition at line 746 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::sanityCheck | ( | ) |
Sanity check for SVFIR.
Definition at line 2267 of file SVFIRBuilder.cpp.
|
protected |
We assume every GepValVar and its GepStmt are unique across whole program
Only the return-value Phi merges at the shared function exit. Aggregate field stores, fallback addresses and a snapshot load before an immediate return belong to the individual return instruction.
CallPE is placed at FunEntryICFGNode (phi-like merging of actual params)
CallPE is phi-like at FunEntryICFGNode. Collect it on each CallCFGEdge whose call site appears as an operand, so the edge knows which params are passed.
Definition at line 2371 of file SVFIRBuilder.cpp.
|
inlineprotected |
Set current basic block in order to keep track of control flow information.
Definition at line 352 of file SVFIRBuilder.h.
|
inlineprotected |
Definition at line 357 of file SVFIRBuilder.h.
| void SVFIRBuilder::updateCallGraph | ( | CallGraph * | callgraph | ) |
connect PAG edges based on callgraph
Definition at line 2232 of file SVFIRBuilder.cpp.
|
virtual |
Our visit overrides.
Visit alloca instructions Add edge V (dst) <– O (src), V here is a value node on SVFIR, O is object node on SVFIR
Definition at line 1041 of file SVFIRBuilder.cpp.
|
inline |
Definition at line 296 of file SVFIRBuilder.h.
|
inline |
Definition at line 300 of file SVFIRBuilder.h.
| void SVFIRBuilder::visitBinaryOperator | ( | BinaryOperator & | inst | ) |
Visit Binary Operator
Definition at line 1181 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitBranchInst | ( | BranchInst & | inst | ) |
Branch and switch instructions are treated as UnaryOP br cmp label if.then, label if.else
set conditional svf var
Definition at line 1847 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitCallBrInst | ( | CallBrInst & | I | ) |
Definition at line 1249 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitCallInst | ( | CallInst & | I | ) |
Definition at line 1239 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitCallSite | ( | CallBase * | cs | ) |
Collect callsite arguments and returns
Definition at line 1257 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitCastInst | ( | CastInst & | I | ) |
Definition at line 1166 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitCmpInst | ( | CmpInst & | inst | ) |
Visit compare instruction
Definition at line 1209 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitExtractElementInst | ( | ExtractElementInst & | inst | ) |
Extract a constant pointer lane using the same field model as extractvalue. For example: a = insertelement <2 x ptr> poison, ptr p, i32 0 b = insertelement <2 x ptr> poison, ptr q, i32 0 s = select i1 cond, <2 x ptr> a, <2 x ptr> b r = extractelement <2 x ptr> s, i32 0
Lane 0 is AggregateField{0}: its copies and conditional SelectStmt are defined at a, b and s, then this visitor copies the lane into r. Dynamic indices, scalable vectors and unsupported lane definitions keep the existing fallback.
Definition at line 1838 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitExtractValueInst | ( | ExtractValueInst & | inst | ) |
Extract a pointer from a register aggregate using its shared field definition. For example: a = insertvalue {ptr} poison, ptr p, 0 b = insertvalue {ptr} poison, ptr q, 0 s = select i1 cond, {ptr} a, {ptr} b r = extractvalue {ptr} s, 0
getAggregateFieldNode(s, {0}, field) creates field copies at a and b and a SelectStmt with cond at s. This visitor adds one CopyStmt from field to r. Further extracts of s's field 0 reuse that definition. Unsupported fields keep the existing black-hole fallback.
Definition at line 1821 of file SVFIRBuilder.cpp.
|
inline |
Definition at line 292 of file SVFIRBuilder.h.
| void SVFIRBuilder::visitFreezeInst | ( | FreezeInst & | inst | ) |
<result> = freeze ty <val> If <val> is undef or poison, ‘freeze’ returns an arbitrary, but fixed value of type ty Otherwise, this instruction is a no-op and returns the input <val>
<result> = freeze ty <val> If <val> is undef or poison, ‘freeze’ returns an arbitrary, but fixed value of type ty Otherwise, this instruction is a no-op and returns the input <val> For now, we assume <val> is never a poison or undef.
Definition at line 1988 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitGetElementPtrInst | ( | GetElementPtrInst & | inst | ) |
Visit getelementptr instructions
Definition at line 1126 of file SVFIRBuilder.cpp.
|
protected |
Handle globals including (global variable and functions)
Visit global variables for building SVFIR
initialize global variable
initialize global functions
Definition at line 987 of file SVFIRBuilder.cpp.
|
inline |
Keep the whole vector defined for full-SVFG consumers. getAggregateFieldNode models supported pointer lanes separately; those definitions do not read this fallback.
Definition at line 272 of file SVFIRBuilder.h.
|
inline |
Keep the whole aggregate defined for full-SVFG consumers. getAggregateFieldNode models demanded pointer fields separately; those definitions do not read this fallback.
Definition at line 243 of file SVFIRBuilder.h.
|
inline |
Provide base case for our instruction visit.
Definition at line 306 of file SVFIRBuilder.h.
| void SVFIRBuilder::visitInvokeInst | ( | InvokeInst & | II | ) |
Definition at line 1244 of file SVFIRBuilder.cpp.
|
inline |
Definition at line 280 of file SVFIRBuilder.h.
| void SVFIRBuilder::visitLoadInst | ( | LoadInst & | I | ) |
Definition at line 1086 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitPHINode | ( | PHINode & | inst | ) |
Visit phi instructions
Definition at line 1060 of file SVFIRBuilder.cpp.
|
inline |
| void SVFIRBuilder::visitReturnInst | ( | ReturnInst & | inst | ) |
Visit return instructions of a function
Definition at line 1310 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitSelectInst | ( | SelectInst & | inst | ) |
Visit select instructions
Two operands have same incoming basic block, both are the current BB
Definition at line 1225 of file SVFIRBuilder.cpp.
|
inline |
Definition at line 276 of file SVFIRBuilder.h.
| void SVFIRBuilder::visitStoreInst | ( | StoreInst & | inst | ) |
Visit store instructions
Definition at line 1104 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitSwitchInst | ( | SwitchInst & | inst | ) |
Preserve LLVM switch destinations and case values in BranchStmt.
See more: https://github.com/SVF-tools/SVF/pull/1191
Given the code:
switch (a) { case 0: printf("0\n"); break; case 1: case 2: case 3: printf("a >=1 && a <= 3\n"); break; case 4: case 6: case 7: printf("a >= 4 && a <=7\n"); break; default: printf("a < 0 || a > 7"); break; }
Generate the IR:
switch i32 %0, label sw.default [ i32 0, label sw.bb i32 1, label sw.bb1 i32 2, label sw.bb1 i32 3, label sw.bb1 i32 4, label sw.bb3 i32 6, label sw.bb3 i32 7, label sw.bb3 ]
We can get every case basic block and related case value: [ {sw.default, -1}, {sw.bb, 0}, {sw.bb1, 1}, {sw.bb1, 2}, {sw.bb1, 3}, {sw.bb3, 4}, {sw.bb3, 6}, {sw.bb3, 7}, ] Note: default case value is nullptr
set conditional svf var
Definition at line 1926 of file SVFIRBuilder.cpp.
| void SVFIRBuilder::visitUnaryOperator | ( | UnaryOperator & | inst | ) |
Visit Unary Operator
Definition at line 1196 of file SVFIRBuilder.cpp.
|
inline |
Definition at line 289 of file SVFIRBuilder.h.
| void SVFIRBuilder::visitVAArgInst | ( | VAArgInst & | inst | ) |
TODO: var arguments need to be handled. https://llvm.org/docs/LangRef.html#id1911
ap = alloca struct.va_list ap2 = bitcast struct.va_list* ap to i8* ; Read a single integer argument from ap2 tmp = va_arg i8* ap2, i32 (VAArgInst) TODO: for now, create a copy edge from ap2 to tmp, we assume here tmp should point to the n-th argument of the var_args
Definition at line 1976 of file SVFIRBuilder.cpp.
|
inline |
Definition at line 258 of file SVFIRBuilder.h.
|
inline |
Definition at line 259 of file SVFIRBuilder.h.
|
inline |
Definition at line 260 of file SVFIRBuilder.h.
Definition at line 51 of file SVFIRBuilder.h.
|
private |
Slot addresses that each call to a modeled callee passes as output arguments, in field-path order, including calls with unused results. visitCallSite appends them after the call's ordinary arguments.
Definition at line 135 of file SVFIRBuilder.h.
|
private |
Reuse the same scalar SVFIR node for repeated requests for a field.
Definition at line 66 of file SVFIRBuilder.h.
|
private |
Output parameters of each modeled callee, in field-path order.
Carry a pointer field from a returned aggregate to its extraction. C example (Clang 21, x86-64 Linux, -O1; noinline preserves the call): struct Pair { int *first, *second; }; attribute((noinline)) struct Pair make(int *p, int *q) { return (struct Pair){p, q}; } int *first(int *p, int *q) { struct Pair a = make(p, q); return a.first; } Corresponding LLVM IR (names simplified, attributes omitted): define {ptr, ptr} @make(ptr p, ptr q) { r0 = insertvalue {ptr, ptr} poison, ptr p, 0 r1 = insertvalue {ptr, ptr} r0, ptr q, 1 ret {ptr, ptr} r1 } define ptr @first(ptr p, ptr q) { a = tail call {ptr, ptr} @make(ptr p, ptr q) x = extractvalue {ptr, ptr} a, 0 ret ptr x } Only field {0} is extracted. For this call, the field uses three distinct SVFIR nodes: obj: a pointer-sized DummyObjVar, called the return slot. This is synthetic storage, not the Pair object or an LLVM alloca. A: a DummyValVar pointing to obj, passed to make. V: a DummyValVar holding the pointer loaded from obj after the call; later uses read V without reloading obj. Each static callsite has its own obj/A/V for each demanded field. make also gets a synthetic output ArgValVar, named out_obj below. Using symbolic node names, the field transport is shown below; ordinary argument/return edges and whole-aggregate fallback edges are omitted: first's call: A = Addr(obj) make's entry: CallPE(A, out_obj) make's r0: F0 = Copy(p) make's r1: F1 = Copy(F0) make's return: Store(F1, out_obj) first's x: V = Load(A); x = Copy(V) insertvalue creates a new aggregate: r0 = {p, poison}, r1 = {p, q}. The second insertion preserves field {0}. F0 models (r0, {0}) and F1 models (r1, {0}); field {1} is not extracted here, so it needs no separate field node. The snapshot load precedes the extraction copy at the same continuation. aggregateReturnParams[make][{0}] holds out_obj. aggregateCallArgs[a][{0}] holds A, and aggregateFieldNodes[(a, {0})] holds V. obj, Addr(obj) and Load(A) are created before instructions are visited; V is loaded at x, the instruction after the call. All calls to make append their own A to match out_obj, even with unused results. More demanded fields follow field-path order. These additions affect only SVFIR; the LLVM signatures above do not change.
Definition at line 131 of file SVFIRBuilder.h.
|
private |
Current basic block during SVFIR construction when visiting the module.
Definition at line 55 of file SVFIRBuilder.h.
Current Value during SVFIR construction when visiting the module.
Definition at line 56 of file SVFIRBuilder.h.
|
private |
Definition at line 54 of file SVFIRBuilder.h.