Added User class, moved operands to User, cleanup
git-svn-id: http://llvm-py.googlecode.com/svn/trunk@69 8d1e9007-1d4e-0410-b67e-1979fd6579aa
This commit is contained in:
parent
10843ec2ec
commit
8b6109d8eb
7 changed files with 144 additions and 154 deletions
14
llvm/_core.c
14
llvm/_core.c
|
|
@ -323,6 +323,11 @@ _wrap_obj2none(LLVMDumpValue, LLVMValueRef)
|
|||
_wrap_dumper(LLVMDumpValueToString, LLVMValueRef)
|
||||
_wrap_obj2obj(LLVMValueGetID, LLVMValueRef, int)
|
||||
|
||||
/*===-- Users ------------------------------------------------------------===*/
|
||||
|
||||
_wrap_obj2obj(LLVMUserGetNumOperands, LLVMValueRef, int)
|
||||
_wrap_objint2obj(LLVMUserGetOperand, LLVMValueRef, LLVMValueRef)
|
||||
|
||||
/*===-- Constant Values --------------------------------------------------===*/
|
||||
|
||||
/* Operations on constants of any type */
|
||||
|
|
@ -534,8 +539,6 @@ _wrap_obj2obj(LLVMInstIsTrapping, LLVMValueRef, int)
|
|||
_wrap_obj2obj(LLVMInstIsVolatile, LLVMValueRef, int)
|
||||
_wrap_obj2obj(LLVMInstGetOpcode, LLVMValueRef, int)
|
||||
_wrap_obj2str(LLVMInstGetOpcodeName, LLVMValueRef)
|
||||
_wrap_obj2obj(LLVMInstGetNumOperands, LLVMValueRef, int)
|
||||
_wrap_objint2obj(LLVMInstGetOperand, LLVMValueRef, LLVMValueRef)
|
||||
|
||||
/*===-- Call Sites (Call or Invoke) --------------------------------------===*/
|
||||
|
||||
|
|
@ -1115,6 +1118,11 @@ static PyMethodDef core_methods[] = {
|
|||
_method( LLVMDumpValueToString )
|
||||
_method( LLVMValueGetID )
|
||||
|
||||
/* Users */
|
||||
|
||||
_method( LLVMUserGetNumOperands )
|
||||
_method( LLVMUserGetOperand )
|
||||
|
||||
/* Constant Values */
|
||||
|
||||
/* Operations on constants of any type */
|
||||
|
|
@ -1255,8 +1263,6 @@ static PyMethodDef core_methods[] = {
|
|||
_method( LLVMInstIsVolatile )
|
||||
_method( LLVMInstGetOpcode )
|
||||
_method( LLVMInstGetOpcodeName )
|
||||
_method( LLVMInstGetNumOperands )
|
||||
_method( LLVMInstGetOperand )
|
||||
|
||||
/* Call Sites (Call or Invoke) */
|
||||
_method( LLVMSetInstructionCallConv )
|
||||
|
|
|
|||
139
llvm/core.py
139
llvm/core.py
|
|
@ -329,6 +329,7 @@ class Module(llvm.Ownable, llvm.Cacheable):
|
|||
Use the static method `Module.new' instead.
|
||||
"""
|
||||
llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeModule)
|
||||
llvm.Cacheable.__init__(self, ptr)
|
||||
|
||||
def __str__(self):
|
||||
"""Text representation of a module.
|
||||
|
|
@ -666,12 +667,6 @@ class Type(object):
|
|||
class IntegerType(Type):
|
||||
"""Represents an integer type."""
|
||||
|
||||
def __init__(self, ptr, kind):
|
||||
"""DO NOT CALL DIRECTLY.
|
||||
|
||||
Use one of the static methods of the *base* class (Type) instead."""
|
||||
Type.__init__(self, ptr, kind)
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
"""The width of the integer type, in bits."""
|
||||
|
|
@ -681,12 +676,6 @@ class IntegerType(Type):
|
|||
class FunctionType(Type):
|
||||
"""Represents a function type."""
|
||||
|
||||
def __init__(self, ptr, kind):
|
||||
"""DO NOT CALL DIRECTLY.
|
||||
|
||||
Use one of the static methods of the *base* class (Type) instead."""
|
||||
Type.__init__(self, ptr, kind)
|
||||
|
||||
@property
|
||||
def return_type(self):
|
||||
"""The type of the value returned by this function."""
|
||||
|
|
@ -717,12 +706,6 @@ class FunctionType(Type):
|
|||
class StructType(Type):
|
||||
"""Represents a structure type."""
|
||||
|
||||
def __init__(self, ptr, kind):
|
||||
"""DO NOT CALL DIRECTLY.
|
||||
|
||||
Use one of the static methods of the *base* class (Type) instead."""
|
||||
Type.__init__(self, ptr, kind)
|
||||
|
||||
@property
|
||||
def element_count(self):
|
||||
"""Number of elements (members) in the structure.
|
||||
|
|
@ -746,12 +729,6 @@ class StructType(Type):
|
|||
class ArrayType(Type):
|
||||
"""Represents an array type."""
|
||||
|
||||
def __init__(self, ptr, kind):
|
||||
"""DO NOT CALL DIRECTLY.
|
||||
|
||||
Use one of the static methods of the *base* class (Type) instead."""
|
||||
Type.__init__(self, ptr, kind)
|
||||
|
||||
@property
|
||||
def element(self):
|
||||
ptr = _core.LLVMGetElementType(self.ptr)
|
||||
|
|
@ -765,12 +742,6 @@ class ArrayType(Type):
|
|||
|
||||
class PointerType(Type):
|
||||
|
||||
def __init__(self, ptr, kind):
|
||||
"""DO NOT CALL DIRECTLY.
|
||||
|
||||
Use one of the static methods of the *base* class (Type) instead."""
|
||||
Type.__init__(self, ptr, kind)
|
||||
|
||||
@property
|
||||
def pointee(self):
|
||||
ptr = _core.LLVMGetElementType(self.ptr)
|
||||
|
|
@ -784,12 +755,6 @@ class PointerType(Type):
|
|||
|
||||
class VectorType(Type):
|
||||
|
||||
def __init__(self, ptr, kind):
|
||||
"""DO NOT CALL DIRECTLY.
|
||||
|
||||
Use one of the static methods of the *base* class (Type) instead."""
|
||||
Type.__init__(self, ptr, kind)
|
||||
|
||||
@property
|
||||
def element(self):
|
||||
ptr = _core.LLVMGetElementType(self.ptr)
|
||||
|
|
@ -854,6 +819,7 @@ class TypeHandle(object):
|
|||
class Value(llvm.Cacheable):
|
||||
|
||||
def __init__(self, ptr):
|
||||
llvm.Cacheable.__init__(self, ptr)
|
||||
self.ptr = ptr
|
||||
|
||||
def __str__(self):
|
||||
|
|
@ -887,7 +853,22 @@ class Value(llvm.Cacheable):
|
|||
return _make_type(ptr, kind)
|
||||
|
||||
|
||||
class Constant(Value):
|
||||
class User(Value):
|
||||
|
||||
@property
|
||||
def operand_count(self):
|
||||
return _core.LLVMUserGetNumOperands(self.ptr)
|
||||
|
||||
@property
|
||||
def operands(self):
|
||||
"""Yields operands of this instruction."""
|
||||
return [self._get_operand(i) for i in range(self.operand_count)]
|
||||
|
||||
def _get_operand(self, i):
|
||||
return _make_value(_core.LLVMUserGetOperand(self.ptr, i))
|
||||
|
||||
|
||||
class Constant(User):
|
||||
|
||||
@staticmethod
|
||||
def null(ty):
|
||||
|
|
@ -956,9 +937,6 @@ class Constant(Value):
|
|||
check_is_type(ty)
|
||||
return _make_value(_core.LLVMSizeOf(ty.ptr))
|
||||
|
||||
def __init__(self, ptr):
|
||||
Value.__init__(self, ptr)
|
||||
|
||||
def neg(self):
|
||||
return _make_value(_core.LLVMConstNeg(self.ptr))
|
||||
|
||||
|
|
@ -1121,51 +1099,39 @@ class Constant(Value):
|
|||
|
||||
|
||||
class ConstantExpr(Constant):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Constant.__init__(self, ptr)
|
||||
pass
|
||||
|
||||
|
||||
class ConstantAggregateZero(Constant):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Constant.__init__(self, ptr)
|
||||
pass
|
||||
|
||||
|
||||
class ConstantInt(Constant):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Constant.__init__(self, ptr)
|
||||
pass
|
||||
|
||||
|
||||
class ConstantFP(Constant):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Constant.__init__(self, ptr)
|
||||
pass
|
||||
|
||||
|
||||
class ConstantArray(Constant):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Constant.__init__(self, ptr)
|
||||
pass
|
||||
|
||||
|
||||
class ConstantStruct(Constant):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Constant.__init__(self, ptr)
|
||||
pass
|
||||
|
||||
|
||||
class ConstantVector(Constant):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Constant.__init__(self, ptr)
|
||||
pass
|
||||
|
||||
|
||||
class ConstantPointerNull(Constant):
|
||||
pass
|
||||
|
||||
def __init__(self, ptr):
|
||||
Constant.__init__(self, ptr)
|
||||
|
||||
class UndefValue(Constant):
|
||||
pass
|
||||
|
||||
|
||||
class GlobalValue(Constant):
|
||||
|
|
@ -1228,9 +1194,6 @@ class GlobalVariable(GlobalValue):
|
|||
raise llvm.LLVMException, ("no global named `%s`" % name)
|
||||
return _make_value(ptr)
|
||||
|
||||
def __init__(self, ptr):
|
||||
GlobalValue.__init__(self, ptr)
|
||||
|
||||
def delete(self):
|
||||
self._delete()
|
||||
_core.LLVMDeleteGlobal(self.ptr)
|
||||
|
|
@ -1262,9 +1225,6 @@ class GlobalVariable(GlobalValue):
|
|||
|
||||
class Argument(Value):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Value.__init__(self, ptr)
|
||||
|
||||
def add_attribute(self, attr):
|
||||
_core.LLVMAddAttribute(self.ptr, attr)
|
||||
|
||||
|
|
@ -1306,9 +1266,6 @@ class Function(GlobalValue):
|
|||
return _make_value(
|
||||
_core.LLVMGetIntrinsic(module.ptr, intrinsic_id, ptrs))
|
||||
|
||||
def __init__(self, ptr):
|
||||
GlobalValue.__init__(self, ptr)
|
||||
|
||||
def delete(self):
|
||||
self._delete()
|
||||
_core.LLVMDeleteFunction(self.ptr)
|
||||
|
|
@ -1336,11 +1293,16 @@ class Function(GlobalValue):
|
|||
def basic_block_count(self):
|
||||
return _core.LLVMCountBasicBlocks(self.ptr)
|
||||
|
||||
def get_entry_basic_block(self):
|
||||
@property
|
||||
def entry_basic_block(self):
|
||||
if self.basic_block_count == 0:
|
||||
return None
|
||||
return _make_value(_core.LLVMGetEntryBasicBlock(self.ptr))
|
||||
|
||||
def get_entry_basic_block(self):
|
||||
"""Deprecated, use entry_basic_block property."""
|
||||
return self.entry_basic_block
|
||||
|
||||
def append_basic_block(self, name):
|
||||
return _make_value(_core.LLVMAppendBasicBlock(self.ptr, name))
|
||||
|
||||
|
|
@ -1365,10 +1327,7 @@ class Function(GlobalValue):
|
|||
# Instruction
|
||||
#===----------------------------------------------------------------------===
|
||||
|
||||
class Instruction(Value):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Value.__init__(self, ptr)
|
||||
class Instruction(User):
|
||||
|
||||
@property
|
||||
def basic_block(self):
|
||||
|
|
@ -1423,24 +1382,9 @@ class Instruction(Value):
|
|||
def opcode_name(self):
|
||||
return _core.LLVMInstGetOpcodeName(self.ptr)
|
||||
|
||||
@property
|
||||
def operand_count(self):
|
||||
return _core.LLVMInstGetNumOperands(self.ptr)
|
||||
|
||||
@property
|
||||
def operands(self):
|
||||
"""Yields operands of this instruction."""
|
||||
return [self._get_operand(i) for i in range(self.operand_count)]
|
||||
|
||||
def _get_operand(self, i):
|
||||
return _make_value(_core.LLVMInstGetOperand(self.ptr, i))
|
||||
|
||||
|
||||
class CallOrInvokeInstruction(Instruction):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Instruction.__init__(self, ptr)
|
||||
|
||||
def _get_cc(self): return _core.LLVMGetInstructionCallConv(self.ptr)
|
||||
def _set_cc(self, value): _core.LLVMSetInstructionCallConv(self.ptr, value)
|
||||
calling_convention = property(_get_cc, _set_cc)
|
||||
|
|
@ -1457,9 +1401,6 @@ class CallOrInvokeInstruction(Instruction):
|
|||
|
||||
class PHINode(Instruction):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Instruction.__init__(self, ptr)
|
||||
|
||||
@property
|
||||
def incoming_count(self):
|
||||
return _core.LLVMCountIncoming(self.ptr)
|
||||
|
|
@ -1478,9 +1419,6 @@ class PHINode(Instruction):
|
|||
|
||||
class SwitchInstruction(Instruction):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Instruction.__init__(self, ptr)
|
||||
|
||||
def add_case(self, const, bblk):
|
||||
check_is_constant(const) # and has to be an int too
|
||||
check_is_basic_block(bblk)
|
||||
|
|
@ -1493,9 +1431,6 @@ class SwitchInstruction(Instruction):
|
|||
|
||||
class BasicBlock(Value):
|
||||
|
||||
def __init__(self, ptr):
|
||||
Value.__init__(self, ptr)
|
||||
|
||||
def insert_before(self, name):
|
||||
return _make_value(_core.LLVMInsertBasicBlock(self.ptr, name))
|
||||
|
||||
|
|
@ -1526,8 +1461,8 @@ __class_for_valueid = {
|
|||
VALUE_FUNCTION : Function,
|
||||
VALUE_GLOBAL_ALIAS : GlobalValue,
|
||||
VALUE_GLOBAL_VARIABLE : GlobalVariable,
|
||||
VALUE_UNDEF_VALUE : UndefValue,
|
||||
VALUE_CONSTANT_EXPR : ConstantExpr,
|
||||
VALUE_INLINE_ASM : Constant,
|
||||
VALUE_CONSTANT_AGGREGATE_ZERO : ConstantAggregateZero,
|
||||
VALUE_CONSTANT_INT : ConstantInt,
|
||||
VALUE_CONSTANT_FP : ConstantFP,
|
||||
|
|
|
|||
|
|
@ -237,21 +237,6 @@ unsigned LLVMInstGetOpcode(LLVMValueRef inst)
|
|||
return instp->getOpcode();
|
||||
}
|
||||
|
||||
unsigned LLVMInstGetNumOperands(LLVMValueRef inst)
|
||||
{
|
||||
llvm::Instruction *instp = llvm::unwrap<llvm::Instruction>(inst);
|
||||
assert(instp);
|
||||
return instp->getNumOperands();
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMInstGetOperand(LLVMValueRef inst, unsigned idx)
|
||||
{
|
||||
llvm::Instruction *instp = llvm::unwrap<llvm::Instruction>(inst);
|
||||
assert(instp);
|
||||
llvm::Value *operand = instp->getOperand(idx);
|
||||
return llvm::wrap(operand);
|
||||
}
|
||||
|
||||
/* llvm::unwrap a set of `n' wrapped objects starting at `values',
|
||||
* into a vector of pointers to llvm::unwrapped objects `out'. */
|
||||
template <typename W, typename UW>
|
||||
|
|
@ -314,6 +299,21 @@ unsigned LLVMValueGetID(LLVMValueRef value)
|
|||
return valuep->getValueID();
|
||||
}
|
||||
|
||||
unsigned LLVMUserGetNumOperands(LLVMValueRef user)
|
||||
{
|
||||
llvm::User *userp = llvm::unwrap<llvm::User>(user);
|
||||
assert(userp);
|
||||
return userp->getNumOperands();
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMUserGetOperand(LLVMValueRef user, unsigned idx)
|
||||
{
|
||||
llvm::User *userp = llvm::unwrap<llvm::User>(user);
|
||||
assert(userp);
|
||||
llvm::Value *operand = userp->getOperand(idx);
|
||||
return llvm::wrap(operand);
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMGetIntrinsic(LLVMModuleRef module, int id,
|
||||
LLVMTypeRef *types, unsigned n_types)
|
||||
{
|
||||
|
|
|
|||
12
llvm/extra.h
12
llvm/extra.h
|
|
@ -69,6 +69,12 @@ LLVMValueRef LLVMBuildGetResult(LLVMBuilderRef builder, LLVMValueRef value,
|
|||
/* Wraps llvm::Value::getValueID(). */
|
||||
unsigned LLVMValueGetID(LLVMValueRef value);
|
||||
|
||||
/* Wraps llvm:User::getNumOperands(). */
|
||||
unsigned LLVMUserGetNumOperands(LLVMValueRef user);
|
||||
|
||||
/* Wraps llvm:User::getOperand(). */
|
||||
LLVMValueRef LLVMUserGetOperand(LLVMValueRef user, unsigned idx);
|
||||
|
||||
/* Wraps llvm::ConstantExpr::getVICmp(). */
|
||||
LLVMValueRef LLVMConstVICmp(LLVMIntPredicate predicate, LLVMValueRef lhs,
|
||||
LLVMValueRef rhs);
|
||||
|
|
@ -121,12 +127,6 @@ const char *LLVMInstGetOpcodeName(LLVMValueRef inst);
|
|||
/* Wraps llvm::Instruction::getOpcode(). */
|
||||
unsigned LLVMInstGetOpcode(LLVMValueRef inst);
|
||||
|
||||
/* Wraps llvm:Instruction::getNumOperands(). */
|
||||
unsigned LLVMInstGetNumOperands(LLVMValueRef inst);
|
||||
|
||||
/* Wraps llvm:Instruction::getOperand(). */
|
||||
LLVMValueRef LLVMInstGetOperand(LLVMValueRef inst, unsigned idx);
|
||||
|
||||
/* Wraps llvm::ParseAssemblyString(). Returns a module reference or NULL (with
|
||||
* `out' pointing to an error message). Dispose error message after use, via
|
||||
* LLVMDisposeMessage(). */
|
||||
|
|
|
|||
|
|
@ -77,11 +77,15 @@ b3 = f1.get_entry_basic_block()
|
|||
check(b1, b3)
|
||||
|
||||
print "Testing basic block aliasing 3 .. ",
|
||||
b31 = f1.entry_basic_block
|
||||
check(b1, b31)
|
||||
|
||||
print "Testing basic block aliasing 4 .. ",
|
||||
bldr = Builder.new(b1)
|
||||
b4 = bldr.basic_block
|
||||
check(b1, b4)
|
||||
|
||||
print "Testing basic block aliasing 4 .. ",
|
||||
print "Testing basic block aliasing 5 .. ",
|
||||
i1 = bldr.ret_void()
|
||||
b5 = i1.basic_block
|
||||
check(b1, b5)
|
||||
|
|
|
|||
|
|
@ -4,40 +4,69 @@
|
|||
|
||||
from llvm.core import *
|
||||
|
||||
m = None
|
||||
|
||||
#===----------------------------------------------------------------------===
|
||||
|
||||
# implement a test function
|
||||
def make_function():
|
||||
test_module = """
|
||||
define i32 @prod(i32, i32) {
|
||||
entry:
|
||||
%2 = mul i32 %0, %1
|
||||
ret i32 %2
|
||||
}
|
||||
test_module = """
|
||||
define i32 @prod(i32, i32) {
|
||||
entry:
|
||||
%2 = mul i32 %0, %1
|
||||
ret i32 %2
|
||||
}
|
||||
|
||||
define i32 @test_func(i32, i32, i32) {
|
||||
entry:
|
||||
%tmp1 = call i32 @prod(i32 %0, i32 %1)
|
||||
%tmp2 = add i32 %tmp1, %2
|
||||
%tmp3 = add i32 %tmp2, 1
|
||||
ret i32 %tmp3
|
||||
}
|
||||
"""
|
||||
class strstream(object):
|
||||
def __init__(self): pass
|
||||
def read(self): return test_module
|
||||
m = Module.from_assembly(strstream())
|
||||
print "-"*60
|
||||
print m
|
||||
print "-"*60
|
||||
print "Examining function `test_func':"
|
||||
return m.get_function_named("test_func")
|
||||
define i32 @test_func(i32, i32, i32) {
|
||||
entry:
|
||||
%tmp1 = call i32 @prod(i32 %0, i32 %1)
|
||||
%tmp2 = add i32 %tmp1, %2
|
||||
%tmp3 = add i32 %tmp2, 1
|
||||
ret i32 %tmp3
|
||||
}
|
||||
"""
|
||||
class strstream(object):
|
||||
def __init__(self): pass
|
||||
def read(self): return test_module
|
||||
m = Module.from_assembly(strstream())
|
||||
print "-"*60
|
||||
print m
|
||||
print "-"*60
|
||||
|
||||
test_func = m.get_function_named("test_func")
|
||||
prod = m.get_function_named("prod")
|
||||
|
||||
#===----------------------------------------------------------------------===
|
||||
# test operands
|
||||
|
||||
func = make_function()
|
||||
print
|
||||
i1 = test_func.basic_blocks[0].instructions[0]
|
||||
i2 = test_func.basic_blocks[0].instructions[1]
|
||||
print "Testing User.operand_count ..",
|
||||
if i1.operand_count == 3 and i2.operand_count == 2:
|
||||
print "OK"
|
||||
else:
|
||||
print "FAIL"
|
||||
|
||||
print "Testing User.operands ..",
|
||||
c1 = i1.operands[0] is prod
|
||||
c2 = i1.operands[1] is test_func.args[0]
|
||||
c3 = i1.operands[2] is test_func.args[1]
|
||||
c4 = i2.operands[0] is i1
|
||||
c5 = i2.operands[1] is test_func.args[2]
|
||||
c6 = len(i1.operands) == 3
|
||||
c7 = len(i2.operands) == 2
|
||||
if c1 and c2 and c3 and c5 and c6 and c7:
|
||||
print "OK"
|
||||
else:
|
||||
print "FAIL"
|
||||
print
|
||||
|
||||
#===----------------------------------------------------------------------===
|
||||
# show test_function
|
||||
|
||||
print "Examining test_function `test_test_func':"
|
||||
idx = 1
|
||||
for inst in func.basic_blocks[0].instructions:
|
||||
for inst in test_func.basic_blocks[0].instructions:
|
||||
print "Instruction #%d:" % (idx,)
|
||||
print " operand_count =", inst.operand_count
|
||||
print " operands:"
|
||||
|
|
|
|||
|
|
@ -168,6 +168,21 @@ def do_value():
|
|||
i = k.value_id
|
||||
|
||||
|
||||
def do_user():
|
||||
m = Module.new('a')
|
||||
ft = Type.function(ti, [ti]*2)
|
||||
f = Function.new(m, ft, 'func')
|
||||
b = f.append_basic_block('a')
|
||||
bb = Builder.new(b)
|
||||
i1 = bb.add(f.args[0], f.args[1])
|
||||
i2 = bb.ret(i1)
|
||||
i1.operand_count == 2
|
||||
i2.operand_count == 1
|
||||
i1.operands[0] is f.args[0]
|
||||
i1.operands[1] is f.args[1]
|
||||
i2.operands[0] is i1
|
||||
|
||||
|
||||
def do_constant():
|
||||
print " Testing class Constant"
|
||||
Constant.null(ti)
|
||||
|
|
@ -475,6 +490,7 @@ def do_llvm_core():
|
|||
do_type()
|
||||
do_typehandle()
|
||||
do_value()
|
||||
do_user()
|
||||
do_constant()
|
||||
do_global_value()
|
||||
do_global_variable()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue