ai-content-maker/.venv/Lib/site-packages/llvmlite/ir/instructions.py

894 lines
31 KiB
Python
Raw Normal View History

2024-05-03 04:18:51 +03:00
"""
Implementation of LLVM IR instructions.
"""
from llvmlite.ir import types
from llvmlite.ir.values import (Block, Function, Value, NamedValue, Constant,
MetaDataArgument, MetaDataString, AttributeSet,
Undefined, ArgumentAttributes)
from llvmlite.ir._utils import _HasMetadata
class Instruction(NamedValue, _HasMetadata):
def __init__(self, parent, typ, opname, operands, name='', flags=()):
super(Instruction, self).__init__(parent, typ, name=name)
assert isinstance(parent, Block)
assert isinstance(flags, (tuple, list))
self.opname = opname
self.operands = operands
self.flags = list(flags)
self.metadata = {}
@property
def function(self):
return self.parent.function
@property
def module(self):
return self.parent.function.module
def descr(self, buf):
opname = self.opname
if self.flags:
opname = ' '.join([opname] + self.flags)
operands = ', '.join([op.get_reference() for op in self.operands])
typ = self.type
metadata = self._stringify_metadata(leading_comma=True)
buf.append("{0} {1} {2}{3}\n"
.format(opname, typ, operands, metadata))
def replace_usage(self, old, new):
if old in self.operands:
ops = []
for op in self.operands:
ops.append(new if op is old else op)
self.operands = tuple(ops)
self._clear_string_cache()
def __repr__(self):
return "<ir.%s %r of type '%s', opname %r, operands %r>" % (
self.__class__.__name__, self.name, self.type,
self.opname, self.operands)
class CallInstrAttributes(AttributeSet):
_known = frozenset(['convergent', 'noreturn', 'nounwind', 'readonly',
'readnone', 'noinline', 'alwaysinline'])
TailMarkerOptions = frozenset(['tail', 'musttail', 'notail'])
class FastMathFlags(AttributeSet):
_known = frozenset(['fast', 'nnan', 'ninf', 'nsz', 'arcp', 'contract',
'afn', 'reassoc'])
class CallInstr(Instruction):
def __init__(self, parent, func, args, name='', cconv=None, tail=None,
fastmath=(), attrs=(), arg_attrs=None):
self.cconv = (func.calling_convention
if cconv is None and isinstance(func, Function)
else cconv)
# For backwards compatibility with previous API of accepting a "truthy"
# value for a hint to the optimizer to potentially tail optimize.
if isinstance(tail, str) and tail in TailMarkerOptions:
pass
elif tail:
tail = "tail"
else:
tail = ""
self.tail = tail
self.fastmath = FastMathFlags(fastmath)
self.attributes = CallInstrAttributes(attrs)
self.arg_attributes = {}
if arg_attrs:
for idx, attrs in arg_attrs.items():
if not (0 <= idx < len(args)):
raise ValueError("Invalid argument index {}"
.format(idx))
self.arg_attributes[idx] = ArgumentAttributes(attrs)
# Fix and validate arguments
args = list(args)
for i in range(len(func.function_type.args)):
arg = args[i]
expected_type = func.function_type.args[i]
if (isinstance(expected_type, types.MetaDataType) and
arg.type != expected_type):
arg = MetaDataArgument(arg)
if arg.type != expected_type:
msg = ("Type of #{0} arg mismatch: {1} != {2}"
.format(1 + i, expected_type, arg.type))
raise TypeError(msg)
args[i] = arg
super(CallInstr, self).__init__(parent, func.function_type.return_type,
"call", [func] + list(args), name=name)
@property
def callee(self):
return self.operands[0]
@callee.setter
def callee(self, newcallee):
self.operands[0] = newcallee
@property
def args(self):
return self.operands[1:]
def replace_callee(self, newfunc):
if newfunc.function_type != self.callee.function_type:
raise TypeError("New function has incompatible type")
self.callee = newfunc
@property
def called_function(self):
"""The callee function"""
return self.callee
def _descr(self, buf, add_metadata):
def descr_arg(i, a):
if i in self.arg_attributes:
attrs = ' '.join(self.arg_attributes[i]._to_list(a.type)) + ' '
else:
attrs = ''
return '{0} {1}{2}'.format(a.type, attrs, a.get_reference())
args = ', '.join([descr_arg(i, a) for i, a in enumerate(self.args)])
fnty = self.callee.function_type
# Only print function type if variable-argument
if fnty.var_arg:
ty = fnty
# Otherwise, just print the return type.
else:
# Fastmath flag work only in this case
ty = fnty.return_type
callee_ref = "{0} {1}".format(ty, self.callee.get_reference())
if self.cconv:
callee_ref = "{0} {1}".format(self.cconv, callee_ref)
tail_marker = ""
if self.tail:
tail_marker = "{0} ".format(self.tail)
fn_attrs = ' ' + ' '.join(self.attributes._to_list(fnty.return_type))\
if self.attributes else ''
fm_attrs = ' ' + ' '.join(self.fastmath._to_list(fnty.return_type))\
if self.fastmath else ''
buf.append("{tail}{op}{fastmath} {callee}({args}){attr}{meta}\n".format(
tail=tail_marker,
op=self.opname,
callee=callee_ref,
fastmath=fm_attrs,
args=args,
attr=fn_attrs,
meta=(self._stringify_metadata(leading_comma=True)
if add_metadata else ""),
))
def descr(self, buf):
self._descr(buf, add_metadata=True)
class InvokeInstr(CallInstr):
def __init__(self, parent, func, args, normal_to, unwind_to, name='',
cconv=None, fastmath=(), attrs=(), arg_attrs=None):
assert isinstance(normal_to, Block)
assert isinstance(unwind_to, Block)
super(InvokeInstr, self).__init__(parent, func, args, name, cconv,
tail=False, fastmath=fastmath,
attrs=attrs, arg_attrs=arg_attrs)
self.opname = "invoke"
self.normal_to = normal_to
self.unwind_to = unwind_to
def descr(self, buf):
super(InvokeInstr, self)._descr(buf, add_metadata=False)
buf.append(" to label {0} unwind label {1}{metadata}\n".format(
self.normal_to.get_reference(),
self.unwind_to.get_reference(),
metadata=self._stringify_metadata(leading_comma=True),
))
class Terminator(Instruction):
def __init__(self, parent, opname, operands):
super(Terminator, self).__init__(parent, types.VoidType(), opname,
operands)
def descr(self, buf):
opname = self.opname
operands = ', '.join(["{0} {1}".format(op.type, op.get_reference())
for op in self.operands])
metadata = self._stringify_metadata(leading_comma=True)
buf.append("{0} {1}{2}".format(opname, operands, metadata))
class PredictableInstr(Instruction):
def set_weights(self, weights):
operands = [MetaDataString(self.module, "branch_weights")]
for w in weights:
if w < 0:
raise ValueError("branch weight must be a positive integer")
operands.append(Constant(types.IntType(32), w))
md = self.module.add_metadata(operands)
self.set_metadata("prof", md)
class Ret(Terminator):
def __init__(self, parent, opname, return_value=None):
operands = [return_value] if return_value is not None else []
super(Ret, self).__init__(parent, opname, operands)
@property
def return_value(self):
if self.operands:
return self.operands[0]
else:
return None
def descr(self, buf):
return_value = self.return_value
metadata = self._stringify_metadata(leading_comma=True)
if return_value is not None:
buf.append("{0} {1} {2}{3}\n"
.format(self.opname, return_value.type,
return_value.get_reference(),
metadata))
else:
buf.append("{0}{1}\n".format(self.opname, metadata))
class Branch(Terminator):
pass
class ConditionalBranch(PredictableInstr, Terminator):
pass
class IndirectBranch(PredictableInstr, Terminator):
def __init__(self, parent, opname, addr):
super(IndirectBranch, self).__init__(parent, opname, [addr])
self.destinations = []
@property
def address(self):
return self.operands[0]
def add_destination(self, block):
assert isinstance(block, Block)
self.destinations.append(block)
def descr(self, buf):
destinations = ["label {0}".format(blk.get_reference())
for blk in self.destinations]
buf.append("indirectbr {0} {1}, [{2}] {3}\n".format(
self.address.type,
self.address.get_reference(),
', '.join(destinations),
self._stringify_metadata(leading_comma=True),
))
class SwitchInstr(PredictableInstr, Terminator):
def __init__(self, parent, opname, val, default):
super(SwitchInstr, self).__init__(parent, opname, [val])
self.default = default
self.cases = []
@property
def value(self):
return self.operands[0]
def add_case(self, val, block):
assert isinstance(block, Block)
if not isinstance(val, Value):
val = Constant(self.value.type, val)
self.cases.append((val, block))
def descr(self, buf):
cases = ["{0} {1}, label {2}".format(val.type, val.get_reference(),
blk.get_reference())
for val, blk in self.cases]
buf.append("switch {0} {1}, label {2} [{3}] {4}\n".format(
self.value.type,
self.value.get_reference(),
self.default.get_reference(),
' '.join(cases),
self._stringify_metadata(leading_comma=True),
))
class Resume(Terminator):
pass
class SelectInstr(Instruction):
def __init__(self, parent, cond, lhs, rhs, name='', flags=()):
assert lhs.type == rhs.type
super(SelectInstr, self).__init__(parent, lhs.type, "select",
[cond, lhs, rhs], name=name,
flags=flags)
@property
def cond(self):
return self.operands[0]
@property
def lhs(self):
return self.operands[1]
@property
def rhs(self):
return self.operands[2]
def descr(self, buf):
buf.append("select {0} {1} {2}, {3} {4}, {5} {6} {7}\n".format(
' '.join(self.flags),
self.cond.type, self.cond.get_reference(),
self.lhs.type, self.lhs.get_reference(),
self.rhs.type, self.rhs.get_reference(),
self._stringify_metadata(leading_comma=True),
))
class CompareInstr(Instruction):
# Define the following in subclasses
OPNAME = 'invalid-compare'
VALID_OP = {}
def __init__(self, parent, op, lhs, rhs, name='', flags=[]):
if op not in self.VALID_OP:
raise ValueError("invalid comparison %r for %s" % (op, self.OPNAME))
for flag in flags:
if flag not in self.VALID_FLAG:
raise ValueError("invalid flag %r for %s" % (flag, self.OPNAME))
opname = self.OPNAME
if isinstance(lhs.type, types.VectorType):
typ = types.VectorType(types.IntType(1), lhs.type.count)
else:
typ = types.IntType(1)
super(CompareInstr, self).__init__(parent, typ,
opname, [lhs, rhs], flags=flags,
name=name)
self.op = op
def descr(self, buf):
buf.append("{opname}{flags} {op} {ty} {lhs}, {rhs} {meta}\n".format(
opname=self.opname,
flags=''.join(' ' + it for it in self.flags),
op=self.op,
ty=self.operands[0].type,
lhs=self.operands[0].get_reference(),
rhs=self.operands[1].get_reference(),
meta=self._stringify_metadata(leading_comma=True),
))
class ICMPInstr(CompareInstr):
OPNAME = 'icmp'
VALID_OP = {
'eq': 'equal',
'ne': 'not equal',
'ugt': 'unsigned greater than',
'uge': 'unsigned greater or equal',
'ult': 'unsigned less than',
'ule': 'unsigned less or equal',
'sgt': 'signed greater than',
'sge': 'signed greater or equal',
'slt': 'signed less than',
'sle': 'signed less or equal',
}
VALID_FLAG = set()
class FCMPInstr(CompareInstr):
OPNAME = 'fcmp'
VALID_OP = {
'false': 'no comparison, always returns false',
'oeq': 'ordered and equal',
'ogt': 'ordered and greater than',
'oge': 'ordered and greater than or equal',
'olt': 'ordered and less than',
'ole': 'ordered and less than or equal',
'one': 'ordered and not equal',
'ord': 'ordered (no nans)',
'ueq': 'unordered or equal',
'ugt': 'unordered or greater than',
'uge': 'unordered or greater than or equal',
'ult': 'unordered or less than',
'ule': 'unordered or less than or equal',
'une': 'unordered or not equal',
'uno': 'unordered (either nans)',
'true': 'no comparison, always returns true',
}
VALID_FLAG = {'nnan', 'ninf', 'nsz', 'arcp', 'contract', 'afn', 'reassoc',
'fast'}
class CastInstr(Instruction):
def __init__(self, parent, op, val, typ, name=''):
super(CastInstr, self).__init__(parent, typ, op, [val], name=name)
def descr(self, buf):
buf.append("{0} {1} {2} to {3} {4}\n".format(
self.opname,
self.operands[0].type,
self.operands[0].get_reference(),
self.type,
self._stringify_metadata(leading_comma=True),
))
class LoadInstr(Instruction):
def __init__(self, parent, ptr, name=''):
super(LoadInstr, self).__init__(parent, ptr.type.pointee, "load",
[ptr], name=name)
self.align = None
def descr(self, buf):
[val] = self.operands
if self.align is not None:
align = ', align %d' % (self.align)
else:
align = ''
buf.append("load {0}, {1} {2}{3}{4}\n".format(
val.type.pointee,
val.type,
val.get_reference(),
align,
self._stringify_metadata(leading_comma=True),
))
class StoreInstr(Instruction):
def __init__(self, parent, val, ptr):
super(StoreInstr, self).__init__(parent, types.VoidType(), "store",
[val, ptr])
def descr(self, buf):
val, ptr = self.operands
if self.align is not None:
align = ', align %d' % (self.align)
else:
align = ''
buf.append("store {0} {1}, {2} {3}{4}{5}\n".format(
val.type,
val.get_reference(),
ptr.type,
ptr.get_reference(),
align,
self._stringify_metadata(leading_comma=True),
))
class LoadAtomicInstr(Instruction):
def __init__(self, parent, ptr, ordering, align, name=''):
super(LoadAtomicInstr, self).__init__(parent, ptr.type.pointee,
"load atomic", [ptr], name=name)
self.ordering = ordering
self.align = align
def descr(self, buf):
[val] = self.operands
buf.append("load atomic {0}, {1} {2} {3}, align {4}{5}\n".format(
val.type.pointee,
val.type,
val.get_reference(),
self.ordering,
self.align,
self._stringify_metadata(leading_comma=True),
))
class StoreAtomicInstr(Instruction):
def __init__(self, parent, val, ptr, ordering, align):
super(StoreAtomicInstr, self).__init__(parent, types.VoidType(),
"store atomic", [val, ptr])
self.ordering = ordering
self.align = align
def descr(self, buf):
val, ptr = self.operands
buf.append("store atomic {0} {1}, {2} {3} {4}, align {5}{6}\n".format(
val.type,
val.get_reference(),
ptr.type,
ptr.get_reference(),
self.ordering,
self.align,
self._stringify_metadata(leading_comma=True),
))
class AllocaInstr(Instruction):
def __init__(self, parent, typ, count, name):
operands = [count] if count else ()
super(AllocaInstr, self).__init__(parent, typ.as_pointer(), "alloca",
operands, name)
self.align = None
def descr(self, buf):
buf.append("{0} {1}".format(self.opname, self.type.pointee))
if self.operands:
op, = self.operands
buf.append(", {0} {1}".format(op.type, op.get_reference()))
if self.align is not None:
buf.append(", align {0}".format(self.align))
if self.metadata:
buf.append(self._stringify_metadata(leading_comma=True))
class GEPInstr(Instruction):
def __init__(self, parent, ptr, indices, inbounds, name):
typ = ptr.type
lasttyp = None
lastaddrspace = 0
for i in indices:
lasttyp, typ = typ, typ.gep(i)
# inherit the addrspace from the last seen pointer
if isinstance(lasttyp, types.PointerType):
lastaddrspace = lasttyp.addrspace
if (not isinstance(typ, types.PointerType) and
isinstance(lasttyp, types.PointerType)):
typ = lasttyp
else:
typ = typ.as_pointer(lastaddrspace)
super(GEPInstr, self).__init__(parent, typ, "getelementptr",
[ptr] + list(indices), name=name)
self.pointer = ptr
self.indices = indices
self.inbounds = inbounds
def descr(self, buf):
indices = ['{0} {1}'.format(i.type, i.get_reference())
for i in self.indices]
op = "getelementptr inbounds" if self.inbounds else "getelementptr"
buf.append("{0} {1}, {2} {3}, {4} {5}\n".format(
op,
self.pointer.type.pointee,
self.pointer.type,
self.pointer.get_reference(),
', '.join(indices),
self._stringify_metadata(leading_comma=True),
))
class PhiInstr(Instruction):
def __init__(self, parent, typ, name, flags=()):
super(PhiInstr, self).__init__(parent, typ, "phi", (), name=name,
flags=flags)
self.incomings = []
def descr(self, buf):
incs = ', '.join('[{0}, {1}]'.format(v.get_reference(),
b.get_reference())
for v, b in self.incomings)
buf.append("phi {0} {1} {2} {3}\n".format(
' '.join(self.flags),
self.type,
incs,
self._stringify_metadata(leading_comma=True),
))
def add_incoming(self, value, block):
assert isinstance(block, Block)
self.incomings.append((value, block))
def replace_usage(self, old, new):
self.incomings = [((new if val is old else val), blk)
for (val, blk) in self.incomings]
class ExtractElement(Instruction):
def __init__(self, parent, vector, index, name=''):
if not isinstance(vector.type, types.VectorType):
raise TypeError("vector needs to be of VectorType.")
if not isinstance(index.type, types.IntType):
raise TypeError("index needs to be of IntType.")
typ = vector.type.element
super(ExtractElement, self).__init__(parent, typ, "extractelement",
[vector, index], name=name)
def descr(self, buf):
operands = ", ".join("{0} {1}".format(
op.type, op.get_reference()) for op in self.operands)
buf.append("{opname} {operands}\n".format(
opname=self.opname, operands=operands))
class InsertElement(Instruction):
def __init__(self, parent, vector, value, index, name=''):
if not isinstance(vector.type, types.VectorType):
raise TypeError("vector needs to be of VectorType.")
if not value.type == vector.type.element:
raise TypeError(
"value needs to be of type {} not {}.".format(
vector.type.element, value.type))
if not isinstance(index.type, types.IntType):
raise TypeError("index needs to be of IntType.")
typ = vector.type
super(InsertElement, self).__init__(parent, typ, "insertelement",
[vector, value, index], name=name)
def descr(self, buf):
operands = ", ".join("{0} {1}".format(
op.type, op.get_reference()) for op in self.operands)
buf.append("{opname} {operands}\n".format(
opname=self.opname, operands=operands))
class ShuffleVector(Instruction):
def __init__(self, parent, vector1, vector2, mask, name=''):
if not isinstance(vector1.type, types.VectorType):
raise TypeError("vector1 needs to be of VectorType.")
if vector2 != Undefined:
if vector2.type != vector1.type:
raise TypeError("vector2 needs to be " +
"Undefined or of the same type as vector1.")
if (not isinstance(mask, Constant) or
not isinstance(mask.type, types.VectorType) or
not (isinstance(mask.type.element, types.IntType) and
mask.type.element.width == 32)):
raise TypeError("mask needs to be a constant i32 vector.")
typ = types.VectorType(vector1.type.element, mask.type.count)
index_range = range(vector1.type.count
if vector2 == Undefined
else 2 * vector1.type.count)
if not all(ii.constant in index_range for ii in mask.constant):
raise IndexError(
"mask values need to be in {0}".format(index_range),
)
super(ShuffleVector, self).__init__(parent, typ, "shufflevector",
[vector1, vector2, mask], name=name)
def descr(self, buf):
buf.append("shufflevector {0} {1}\n".format(
", ".join("{0} {1}".format(op.type, op.get_reference())
for op in self.operands),
self._stringify_metadata(leading_comma=True),
))
class ExtractValue(Instruction):
def __init__(self, parent, agg, indices, name=''):
typ = agg.type
try:
for i in indices:
typ = typ.elements[i]
except (AttributeError, IndexError):
raise TypeError("Can't index at %r in %s"
% (list(indices), agg.type))
super(ExtractValue, self).__init__(parent, typ, "extractvalue",
[agg], name=name)
self.aggregate = agg
self.indices = indices
def descr(self, buf):
indices = [str(i) for i in self.indices]
buf.append("extractvalue {0} {1}, {2} {3}\n".format(
self.aggregate.type,
self.aggregate.get_reference(),
', '.join(indices),
self._stringify_metadata(leading_comma=True),
))
class InsertValue(Instruction):
def __init__(self, parent, agg, elem, indices, name=''):
typ = agg.type
try:
for i in indices:
typ = typ.elements[i]
except (AttributeError, IndexError):
raise TypeError("Can't index at %r in %s"
% (list(indices), agg.type))
if elem.type != typ:
raise TypeError("Can only insert %s at %r in %s: got %s"
% (typ, list(indices), agg.type, elem.type))
super(InsertValue, self).__init__(parent, agg.type, "insertvalue",
[agg, elem], name=name)
self.aggregate = agg
self.value = elem
self.indices = indices
def descr(self, buf):
indices = [str(i) for i in self.indices]
buf.append("insertvalue {0} {1}, {2} {3}, {4} {5}\n".format(
self.aggregate.type, self.aggregate.get_reference(),
self.value.type, self.value.get_reference(),
', '.join(indices),
self._stringify_metadata(leading_comma=True),
))
class Unreachable(Instruction):
def __init__(self, parent):
super(Unreachable, self).__init__(parent, types.VoidType(),
"unreachable", (), name='')
def descr(self, buf):
buf += (self.opname, "\n")
class InlineAsm(object):
def __init__(self, ftype, asm, constraint, side_effect=False):
self.type = ftype.return_type
self.function_type = ftype
self.asm = asm
self.constraint = constraint
self.side_effect = side_effect
def descr(self, buf):
sideeffect = 'sideeffect' if self.side_effect else ''
fmt = 'asm {sideeffect} "{asm}", "{constraint}"\n'
buf.append(fmt.format(sideeffect=sideeffect, asm=self.asm,
constraint=self.constraint))
def get_reference(self):
buf = []
self.descr(buf)
return "".join(buf)
def __str__(self):
return "{0} {1}".format(self.type, self.get_reference())
class AtomicRMW(Instruction):
def __init__(self, parent, op, ptr, val, ordering, name):
super(AtomicRMW, self).__init__(parent, val.type, "atomicrmw",
(ptr, val), name=name)
self.operation = op
self.ordering = ordering
def descr(self, buf):
ptr, val = self.operands
fmt = ("atomicrmw {op} {ptrty} {ptr}, {valty} {val} {ordering} "
"{metadata}\n")
buf.append(fmt.format(op=self.operation,
ptrty=ptr.type,
ptr=ptr.get_reference(),
valty=val.type,
val=val.get_reference(),
ordering=self.ordering,
metadata=self._stringify_metadata(
leading_comma=True),
))
class CmpXchg(Instruction):
"""This instruction has changed since llvm3.5. It is not compatible with
older llvm versions.
"""
def __init__(self, parent, ptr, cmp, val, ordering, failordering, name):
outtype = types.LiteralStructType([val.type, types.IntType(1)])
super(CmpXchg, self).__init__(parent, outtype, "cmpxchg",
(ptr, cmp, val), name=name)
self.ordering = ordering
self.failordering = failordering
def descr(self, buf):
ptr, cmpval, val = self.operands
fmt = "cmpxchg {ptrty} {ptr}, {ty} {cmp}, {ty} {val} {ordering} " \
"{failordering} {metadata}\n"
buf.append(fmt.format(ptrty=ptr.type,
ptr=ptr.get_reference(),
ty=cmpval.type,
cmp=cmpval.get_reference(),
val=val.get_reference(),
ordering=self.ordering,
failordering=self.failordering,
metadata=self._stringify_metadata(
leading_comma=True),
))
class _LandingPadClause(object):
def __init__(self, value):
self.value = value
def __str__(self):
return "{kind} {type} {value}".format(
kind=self.kind,
type=self.value.type,
value=self.value.get_reference())
class CatchClause(_LandingPadClause):
kind = 'catch'
class FilterClause(_LandingPadClause):
kind = 'filter'
def __init__(self, value):
assert isinstance(value, Constant)
assert isinstance(value.type, types.ArrayType)
super(FilterClause, self).__init__(value)
class LandingPadInstr(Instruction):
def __init__(self, parent, typ, name='', cleanup=False):
super(LandingPadInstr, self).__init__(parent, typ, "landingpad", [],
name=name)
self.cleanup = cleanup
self.clauses = []
def add_clause(self, clause):
assert isinstance(clause, _LandingPadClause)
self.clauses.append(clause)
def descr(self, buf):
fmt = "landingpad {type}{cleanup}{clauses}\n"
buf.append(fmt.format(type=self.type,
cleanup=' cleanup' if self.cleanup else '',
clauses=''.join(["\n {0}".format(clause)
for clause in self.clauses]),
))
class Fence(Instruction):
"""
The `fence` instruction.
As of LLVM 5.0.1:
fence [syncscope("<target-scope>")] <ordering> ; yields void
"""
VALID_FENCE_ORDERINGS = {"acquire", "release", "acq_rel", "seq_cst"}
def __init__(self, parent, ordering, targetscope=None, name=''):
super(Fence, self).__init__(parent, types.VoidType(), "fence", (),
name=name)
if ordering not in self.VALID_FENCE_ORDERINGS:
msg = "Invalid fence ordering \"{0}\"! Should be one of {1}."
raise ValueError(msg .format(ordering,
", ".join(self.VALID_FENCE_ORDERINGS)))
self.ordering = ordering
self.targetscope = targetscope
def descr(self, buf):
if self.targetscope is None:
syncscope = ""
else:
syncscope = 'syncscope("{0}") '.format(self.targetscope)
fmt = "fence {syncscope}{ordering}\n"
buf.append(fmt.format(syncscope=syncscope,
ordering=self.ordering,
))
class Comment(Instruction):
"""
A line comment.
"""
def __init__(self, parent, text):
super(Comment, self).__init__(parent, types.VoidType(), ";", (),
name='')
assert "\n" not in text, "Comment cannot contain new line"
self.text = text
def descr(self, buf):
buf.append(f"; {self.text}")