forked from M-Labs/artiq
transforms.llvm_ir_generator: extract class function attributes.
This should give LLVM more visibility.
This commit is contained in:
parent
39599d4508
commit
39d23793a4
|
@ -618,6 +618,8 @@ class LLVMIRGenerator:
|
||||||
llvalue = self.llbuilder.insert_value(llvalue, self.map(elt), index)
|
llvalue = self.llbuilder.insert_value(llvalue, self.map(elt), index)
|
||||||
llvalue.name = insn.name
|
llvalue.name = insn.name
|
||||||
return llvalue
|
return llvalue
|
||||||
|
elif types.is_constructor(insn.type):
|
||||||
|
return self.get_class(insn.type)
|
||||||
else: # catchall for exceptions and custom (allocated) classes
|
else: # catchall for exceptions and custom (allocated) classes
|
||||||
llalloc = self.llbuilder.alloca(self.llty_of_type(insn.type, bare=True))
|
llalloc = self.llbuilder.alloca(self.llty_of_type(insn.type, bare=True))
|
||||||
for index, operand in enumerate(insn.operands):
|
for index, operand in enumerate(insn.operands):
|
||||||
|
@ -666,16 +668,28 @@ class LLVMIRGenerator:
|
||||||
def attr_index(self, typ, attr):
|
def attr_index(self, typ, attr):
|
||||||
return list(typ.attributes.keys()).index(attr)
|
return list(typ.attributes.keys()).index(attr)
|
||||||
|
|
||||||
def get_class(self, typ):
|
def get_or_define_global(self, name, llty, llvalue=None):
|
||||||
assert types.is_constructor(typ)
|
|
||||||
name = "class.{}".format(typ.name)
|
|
||||||
if name in self.llmodule.globals:
|
if name in self.llmodule.globals:
|
||||||
llglobal = self.llmodule.get_global(name)
|
llglobal = self.llmodule.get_global(name)
|
||||||
else:
|
else:
|
||||||
llty = self.llty_of_type(typ)
|
llglobal = ll.GlobalVariable(self.llmodule, llty, name)
|
||||||
llglobal = ll.GlobalVariable(self.llmodule, llty.pointee, name)
|
if llvalue is not None:
|
||||||
|
llglobal.linkage = "private"
|
||||||
|
llglobal.initializer = llvalue
|
||||||
return llglobal
|
return llglobal
|
||||||
|
|
||||||
|
def get_class(self, typ):
|
||||||
|
assert types.is_constructor(typ)
|
||||||
|
llty = self.llty_of_type(typ).pointee
|
||||||
|
return self.get_or_define_global("class.{}".format(typ.name), llty)
|
||||||
|
|
||||||
|
def get_closure(self, typ, attr):
|
||||||
|
assert types.is_constructor(typ)
|
||||||
|
assert types.is_function(typ.attributes[attr])
|
||||||
|
llty = self.llty_of_type(typ.attributes[attr])
|
||||||
|
return self.get_or_define_global("method.{}.{}".format(typ.name, attr),
|
||||||
|
llty, ll.Constant(llty, ll.Undefined))
|
||||||
|
|
||||||
def process_GetAttr(self, insn):
|
def process_GetAttr(self, insn):
|
||||||
typ, attr = insn.object().type, insn.attr
|
typ, attr = insn.object().type, insn.attr
|
||||||
if types.is_tuple(typ):
|
if types.is_tuple(typ):
|
||||||
|
@ -695,20 +709,24 @@ class LLVMIRGenerator:
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
llptr = self.llbuilder.gep(obj, [self.llindex(0), self.llindex(index)],
|
|
||||||
inbounds=True, name=insn.name)
|
|
||||||
llclosure = self.llbuilder.load(llptr)
|
|
||||||
|
|
||||||
if types.is_method(insn.type) and attr not in typ.attributes:
|
if types.is_method(insn.type) and attr not in typ.attributes:
|
||||||
|
llfun = self.llbuilder.load(self.get_closure(typ.constructor, attr))
|
||||||
|
llself = self.map(insn.object())
|
||||||
|
|
||||||
llmethodty = self.llty_of_type(insn.type)
|
llmethodty = self.llty_of_type(insn.type)
|
||||||
llmethod = ll.Constant(llmethodty, ll.Undefined)
|
llmethod = ll.Constant(llmethodty, ll.Undefined)
|
||||||
llmethod = self.llbuilder.insert_value(llmethod, llclosure,
|
llmethod = self.llbuilder.insert_value(llmethod, llfun,
|
||||||
self.attr_index(insn.type, '__func__'))
|
self.attr_index(insn.type, '__func__'))
|
||||||
llmethod = self.llbuilder.insert_value(llmethod, self.map(insn.object()),
|
llmethod = self.llbuilder.insert_value(llmethod, llself,
|
||||||
self.attr_index(insn.type, '__self__'))
|
self.attr_index(insn.type, '__self__'))
|
||||||
return llmethod
|
return llmethod
|
||||||
|
elif types.is_function(insn.type) and attr in typ.attributes and \
|
||||||
|
types.is_constructor(typ):
|
||||||
|
return self.llbuilder.load(self.get_closure(typ, attr))
|
||||||
else:
|
else:
|
||||||
return llclosure
|
llptr = self.llbuilder.gep(obj, [self.llindex(0), self.llindex(index)],
|
||||||
|
inbounds=True, name=insn.name)
|
||||||
|
return self.llbuilder.load(llptr)
|
||||||
|
|
||||||
def process_SetAttr(self, insn):
|
def process_SetAttr(self, insn):
|
||||||
typ, attr = insn.object().type, insn.attr
|
typ, attr = insn.object().type, insn.attr
|
||||||
|
@ -722,9 +740,13 @@ class LLVMIRGenerator:
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
llptr = self.llbuilder.gep(obj, [self.llindex(0),
|
if types.is_function(insn.value().type) and attr in typ.attributes and \
|
||||||
self.llindex(self.attr_index(typ, attr))],
|
types.is_constructor(typ):
|
||||||
inbounds=True, name=insn.name)
|
llptr = self.get_closure(typ, attr)
|
||||||
|
else:
|
||||||
|
llptr = self.llbuilder.gep(obj, [self.llindex(0),
|
||||||
|
self.llindex(self.attr_index(typ, attr))],
|
||||||
|
inbounds=True, name=insn.name)
|
||||||
return self.llbuilder.store(self.map(insn.value()), llptr)
|
return self.llbuilder.store(self.map(insn.value()), llptr)
|
||||||
|
|
||||||
def process_GetElem(self, insn):
|
def process_GetElem(self, insn):
|
||||||
|
|
Loading…
Reference in New Issue