<s> from __future__ import print_function , absolute_import <EOL> import contextlib <EOL> import functools <EOL> from . import instructions , types , values <EOL> _CMP_MAP = { <EOL> '<STR_LIT:>>' : '<STR_LIT>' , <EOL> '<STR_LIT:<>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> } <EOL> def _binop ( opname , cls = instructions . Instruction ) : <EOL> def wrap ( fn ) : <EOL> @ functools . wraps ( fn ) <EOL> def wrapped ( self , lhs , rhs , name = '<STR_LIT>' , flags = ( ) ) : <EOL> if lhs . type != rhs . type : <EOL> raise ValueError ( "<STR_LIT>" <EOL> % ( lhs . type , rhs . type ) ) <EOL> instr = cls ( self . block , lhs . type , opname , ( lhs , rhs ) , name , flags ) <EOL> self . _insert ( instr ) <EOL> return instr <EOL> return wrapped <EOL> return wrap <EOL> def _binop_with_overflow ( opname , cls = instructions . Instruction ) : <EOL> def wrap ( fn ) : <EOL> @ functools . wraps ( fn ) <EOL> def wrapped ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> if lhs . type != rhs . type : <EOL> raise ValueError ( "<STR_LIT>" <EOL> % ( lhs . type , rhs . type ) ) <EOL> ty = lhs . type <EOL> if not isinstance ( ty , types . IntType ) : <EOL> raise TypeError ( "<STR_LIT>" % ( ty , ) ) <EOL> bool_ty = types . IntType ( <NUM_LIT:1> ) <EOL> mod = self . module <EOL> fnty = types . FunctionType ( types . LiteralStructType ( [ ty , bool_ty ] ) , <EOL> [ ty , ty ] ) <EOL> fn = mod . declare_intrinsic ( "<STR_LIT>" % ( opname , ) , <EOL> [ ty ] , fnty ) <EOL> ret = self . call ( fn , [ lhs , rhs ] , name = name ) <EOL> return ret <EOL> return wrapped <EOL> return wrap <EOL> def _uniop ( opname , cls = instructions . Instruction ) : <EOL> def wrap ( fn ) : <EOL> @ functools . wraps ( fn ) <EOL> def wrapped ( self , operand , name = '<STR_LIT>' ) : <EOL> instr = cls ( self . block , operand . type , opname , [ operand ] , name ) <EOL> self . _insert ( instr ) <EOL> return instr <EOL> return wrapped <EOL> return wrap <EOL> def _castop ( opname , cls = instructions . CastInstr ) : <EOL> def wrap ( fn ) : <EOL> @ functools . wraps ( fn ) <EOL> def wrapped ( self , val , typ , name = '<STR_LIT>' ) : <EOL> if val . type == typ : <EOL> return val <EOL> instr = cls ( self . block , opname , val , typ , name ) <EOL> self . _insert ( instr ) <EOL> return instr <EOL> return wrapped <EOL> return wrap <EOL> class IRBuilder ( object ) : <EOL> def __init__ ( self , block = None ) : <EOL> self . _block = block <EOL> self . _anchor = len ( block . instructions ) if block else <NUM_LIT:0> <EOL> self . debug_metadata = None <EOL> @ property <EOL> def block ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _block <EOL> basic_block = block <EOL> @ property <EOL> def function ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . block . parent <EOL> @ property <EOL> def module ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . block . parent . module <EOL> def position_before ( self , instr ) : <EOL> """<STR_LIT>""" <EOL> self . _block = instr . parent <EOL> self . _anchor = self . _block . instructions . index ( instr ) <EOL> def position_after ( self , instr ) : <EOL> """<STR_LIT>""" <EOL> self . _block = instr . parent <EOL> self . _anchor = self . _block . instructions . index ( instr ) + <NUM_LIT:1> <EOL> def position_at_start ( self , block ) : <EOL> """<STR_LIT>""" <EOL> self . _block = block <EOL> self . _anchor = <NUM_LIT:0> <EOL> def position_at_end ( self , block ) : <EOL> """<STR_LIT>""" <EOL> self . _block = block <EOL> self . _anchor = len ( block . instructions ) <EOL> def append_basic_block ( self , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> return self . function . append_basic_block ( name ) <EOL> @ contextlib . contextmanager <EOL> def goto_block ( self , block ) : <EOL> """<STR_LIT>""" <EOL> old_block = self . basic_block <EOL> term = block . terminator <EOL> if term is not None : <EOL> self . position_before ( term ) <EOL> else : <EOL> self . position_at_end ( block ) <EOL> try : <EOL> yield <EOL> finally : <EOL> self . position_at_end ( old_block ) <EOL> @ contextlib . contextmanager <EOL> def goto_entry_block ( self ) : <EOL> """<STR_LIT>""" <EOL> with self . goto_block ( self . function . entry_basic_block ) : <EOL> yield <EOL> @ contextlib . contextmanager <EOL> def _branch_helper ( self , bbenter , bbexit ) : <EOL> self . position_at_end ( bbenter ) <EOL> yield bbexit <EOL> if self . basic_block . terminator is None : <EOL> self . branch ( bbexit ) <EOL> @ contextlib . contextmanager <EOL> def if_then ( self , pred , likely = None ) : <EOL> """<STR_LIT>""" <EOL> bb = self . basic_block <EOL> bbif = self . append_basic_block ( name = bb . name + '<STR_LIT>' ) <EOL> bbend = self . append_basic_block ( name = bb . name + '<STR_LIT>' ) <EOL> br = self . cbranch ( pred , bbif , bbend ) <EOL> if likely is not None : <EOL> br . set_weights ( [ <NUM_LIT> , <NUM_LIT:1> ] if likely else [ <NUM_LIT:1> , <NUM_LIT> ] ) <EOL> with self . _branch_helper ( bbif , bbend ) : <EOL> yield bbend <EOL> self . position_at_end ( bbend ) <EOL> @ contextlib . contextmanager <EOL> def if_else ( self , pred , likely = None ) : <EOL> """<STR_LIT>""" <EOL> bb = self . basic_block <EOL> bbif = self . append_basic_block ( name = bb . name + '<STR_LIT>' ) <EOL> bbelse = self . append_basic_block ( name = bb . name + '<STR_LIT>' ) <EOL> bbend = self . append_basic_block ( name = bb . name + '<STR_LIT>' ) <EOL> br = self . cbranch ( pred , bbif , bbelse ) <EOL> if likely is not None : <EOL> br . set_weights ( [ <NUM_LIT> , <NUM_LIT:1> ] if likely else [ <NUM_LIT:1> , <NUM_LIT> ] ) <EOL> then = self . _branch_helper ( bbif , bbend ) <EOL> otherwise = self . _branch_helper ( bbelse , bbend ) <EOL> yield then , otherwise <EOL> self . position_at_end ( bbend ) <EOL> def _insert ( self , instr ) : <EOL> if self . debug_metadata is not None and '<STR_LIT>' not in instr . metadata : <EOL> instr . metadata [ '<STR_LIT>' ] = self . debug_metadata <EOL> self . _block . instructions . insert ( self . _anchor , instr ) <EOL> self . _anchor += <NUM_LIT:1> <EOL> def _set_terminator ( self , term ) : <EOL> assert not self . block . is_terminated <EOL> self . _insert ( term ) <EOL> self . block . terminator = term <EOL> return term <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def shl ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def lshr ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def ashr ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def add ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def fadd ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def sub ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def fsub ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def mul ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def fmul ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def udiv ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def sdiv ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def fdiv ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def urem ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def srem ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def frem ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def or_ ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def and_ ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop ( '<STR_LIT>' ) <EOL> def xor ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop_with_overflow ( '<STR_LIT>' ) <EOL> def sadd_with_overflow ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop_with_overflow ( '<STR_LIT>' ) <EOL> def smul_with_overflow ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop_with_overflow ( '<STR_LIT>' ) <EOL> def ssub_with_overflow ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop_with_overflow ( '<STR_LIT>' ) <EOL> def uadd_with_overflow ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop_with_overflow ( '<STR_LIT>' ) <EOL> def umul_with_overflow ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _binop_with_overflow ( '<STR_LIT>' ) <EOL> def usub_with_overflow ( self , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> def not_ ( self , value , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> return self . xor ( value , values . Constant ( value . type , - <NUM_LIT:1> ) , name = name ) <EOL> def neg ( self , value , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> return self . sub ( values . Constant ( value . type , <NUM_LIT:0> ) , value , name = name ) <EOL> def _icmp ( self , prefix , cmpop , lhs , rhs , name ) : <EOL> try : <EOL> op = _CMP_MAP [ cmpop ] <EOL> except KeyError : <EOL> raise ValueError ( "<STR_LIT>" % ( cmpop , ) ) <EOL> if cmpop not in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> op = prefix + op <EOL> instr = instructions . ICMPInstr ( self . block , op , lhs , rhs , name = name ) <EOL> self . _insert ( instr ) <EOL> return instr <EOL> def icmp_signed ( self , cmpop , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> return self . _icmp ( '<STR_LIT:s>' , cmpop , lhs , rhs , name ) <EOL> def icmp_unsigned ( self , cmpop , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> return self . _icmp ( '<STR_LIT:u>' , cmpop , lhs , rhs , name ) <EOL> def fcmp_ordered ( self , cmpop , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> if cmpop in _CMP_MAP : <EOL> op = '<STR_LIT:o>' + _CMP_MAP [ cmpop ] <EOL> else : <EOL> op = cmpop <EOL> instr = instructions . FCMPInstr ( self . block , op , lhs , rhs , name = name ) <EOL> self . _insert ( instr ) <EOL> return instr <EOL> def fcmp_unordered ( self , cmpop , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> if cmpop in _CMP_MAP : <EOL> op = '<STR_LIT:u>' + _CMP_MAP [ cmpop ] <EOL> else : <EOL> op = cmpop <EOL> instr = instructions . FCMPInstr ( self . block , op , lhs , rhs , name = name ) <EOL> self . _insert ( instr ) <EOL> return instr <EOL> def select ( self , cond , lhs , rhs , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> instr = instructions . SelectInstr ( self . block , cond , lhs , rhs , name = name ) <EOL> self . _insert ( instr ) <EOL> return instr <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def trunc ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def zext ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def sext ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def fptrunc ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def fpext ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def bitcast ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def addrspacecast ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def fptoui ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def uitofp ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def fptosi ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def sitofp ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def ptrtoint ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> @ _castop ( '<STR_LIT>' ) <EOL> def inttoptr ( self , value , typ , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> def alloca ( self , typ , size = None , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> if size is None : <EOL> pass <EOL> elif isinstance ( size , ( values . Value , values . Constant ) ) : <EOL> assert isinstance ( size . type , types . IntType ) <EOL> else : <EOL> size = values . Constant ( types . IntType ( <NUM_LIT:32> ) , size ) <EOL> al = instructions . AllocaInstr ( self . block , typ , size , name ) <EOL> self . _insert ( al ) <EOL> return al <EOL> def load ( self , ptr , name = '<STR_LIT>' , align = None ) : <EOL> """<STR_LIT>""" <EOL> if not isinstance ( ptr . type , types . PointerType ) : <EOL> raise TypeError ( "<STR_LIT>" <EOL> % ( ptr . type , str ( ptr ) ) ) <EOL> ld = instructions . LoadInstr ( self . block , ptr , name ) <EOL> ld . align = align <EOL> self . _insert ( ld ) <EOL> return ld <EOL> def store ( self , value , ptr , align = None ) : <EOL> """<STR_LIT>""" <EOL> if not isinstance ( ptr . type , types . PointerType ) : <EOL> raise TypeError ( "<STR_LIT>" <EOL> % ( ptr . type , str ( ptr ) ) ) <EOL> if ptr . type . pointee != value . type : <EOL> raise TypeError ( "<STR_LIT>" <EOL> % ( value . type , ptr . type ) ) <EOL> st = instructions . StoreInstr ( self . block , value , ptr ) <EOL> st . align = align <EOL> self . _insert ( st ) <EOL> return st <EOL> def switch ( self , value , default ) : <EOL> """<STR_LIT>""" <EOL> swt = instructions . SwitchInstr ( self . block , '<STR_LIT>' , value , default ) <EOL> self . _set_terminator ( swt ) <EOL> return swt <EOL> def branch ( self , target ) : <EOL> """<STR_LIT>""" <EOL> br = instructions . Branch ( self . block , "<STR_LIT>" , [ target ] ) <EOL> self . _set_terminator ( br ) <EOL> return br <EOL> def cbranch ( self , cond , truebr , falsebr ) : <EOL> """<STR_LIT>""" <EOL> br = instructions . ConditionalBranch ( self . block , "<STR_LIT>" , <EOL> [ cond , truebr , falsebr ] ) <EOL> self . _set_terminator ( br ) <EOL> return br <EOL> def branch_indirect ( self , addr ) : <EOL> """<STR_LIT>""" <EOL> br = instructions . IndirectBranch ( self . block , "<STR_LIT>" , addr ) <EOL> self . _set_terminator ( br ) <EOL> return br <EOL> def ret_void ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _set_terminator ( <EOL> instructions . Ret ( self . block , "<STR_LIT>" ) ) <EOL> def ret ( self , value ) : <EOL> """<STR_LIT>""" <EOL> return self . _set_terminator ( <EOL> instructions . Ret ( self . block , "<STR_LIT>" , value ) ) <EOL> def resume ( self , landingpad ) : <EOL> """<STR_LIT>""" <EOL> br = instructions . Branch ( self . block , "<STR_LIT>" , [ landingpad ] ) <EOL> self . _set_terminator ( br ) <EOL> return br <EOL> def call ( self , fn , args , name = '<STR_LIT>' , cconv = None , tail = False ) : <EOL> """<STR_LIT>""" <EOL> inst = instructions . CallInstr ( self . block , fn , args , name = name , <EOL> cconv = cconv , tail = tail ) <EOL> self . _insert ( inst ) <EOL> return inst <EOL> def invoke ( self , fn , args , normal_to , unwind_to , name = '<STR_LIT>' , cconv = None , tail = False ) : <EOL> inst = instructions . InvokeInstr ( self . block , fn , args , normal_to , unwind_to , name = name , <EOL> cconv = cconv ) <EOL> self . _set_terminator ( inst ) <EOL> return inst <EOL> def gep ( self , ptr , indices , inbounds = False , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> instr = instructions . GEPInstr ( self . block , ptr , indices , <EOL> inbounds = inbounds , name = name ) <EOL> self . _insert ( instr ) <EOL> return instr <EOL> def extract_value ( self , agg , idx , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> if not isinstance ( idx , ( tuple , list ) ) : <EOL> idx = [ idx ] <EOL> instr = instructions . ExtractValue ( self . block , agg , idx , name = name ) <EOL> self . _insert ( instr ) <EOL> return instr <EOL> def insert_value ( self , agg , value , idx , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> if not isinstance ( idx , ( tuple , list ) ) : <EOL> idx = [ idx ] <EOL> instr = instructions . InsertValue ( self . block , agg , value , idx , name = name ) <EOL> self . _insert ( instr ) <EOL> return instr <EOL> def phi ( self , typ , name = '<STR_LIT>' ) : <EOL> inst = instructions . PhiInstr ( self . block , typ , name = name ) <EOL> self . _insert ( inst ) <EOL> return inst <EOL> def unreachable ( self ) : <EOL> inst = instructions . Unreachable ( self . block ) <EOL> self . _set_terminator ( inst ) <EOL> return inst <EOL> def atomic_rmw ( self , op , ptr , val , ordering , name = '<STR_LIT>' ) : <EOL> inst = instructions . AtomicRMW ( self . block , op , ptr , val , ordering , name = name ) <EOL> self . _insert ( inst ) <EOL> return inst <EOL> def cmpxchg ( self , ptr , cmp , val , ordering , failordering = None , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> failordering = ordering if failordering is None else failordering <EOL> inst = instructions . CmpXchg ( self . block , ptr , cmp , val , ordering , <EOL> failordering , name = name ) <EOL> self . _insert ( inst ) <EOL> return inst <EOL> def landingpad ( self , typ , name = '<STR_LIT>' , cleanup = False ) : <EOL> inst = instructions . LandingPadInstr ( self . block , typ , name , cleanup ) <EOL> self . _insert ( inst ) <EOL> return inst <EOL> def assume ( self , cond ) : <EOL> """<STR_LIT>""" <EOL> fn = self . module . declare_intrinsic ( "<STR_LIT>" ) <EOL> return self . call ( fn , [ cond ] ) </s>
