forked from M-Labs/artiq
1
0
Fork 0

transforms.llvm_ir_generator: extract class function attributes.

This should give LLVM more visibility.
This commit is contained in:
whitequark 2016-03-24 18:27:27 +00:00
parent 39599d4508
commit 39d23793a4
1 changed files with 37 additions and 15 deletions

View File

@ -618,6 +618,8 @@ class LLVMIRGenerator:
llvalue = self.llbuilder.insert_value(llvalue, self.map(elt), index)
llvalue.name = insn.name
return llvalue
elif types.is_constructor(insn.type):
return self.get_class(insn.type)
else: # catchall for exceptions and custom (allocated) classes
llalloc = self.llbuilder.alloca(self.llty_of_type(insn.type, bare=True))
for index, operand in enumerate(insn.operands):
@ -666,16 +668,28 @@ class LLVMIRGenerator:
def attr_index(self, typ, attr):
return list(typ.attributes.keys()).index(attr)
def get_class(self, typ):
assert types.is_constructor(typ)
name = "class.{}".format(typ.name)
def get_or_define_global(self, name, llty, llvalue=None):
if name in self.llmodule.globals:
llglobal = self.llmodule.get_global(name)
else:
llty = self.llty_of_type(typ)
llglobal = ll.GlobalVariable(self.llmodule, llty.pointee, name)
llglobal = ll.GlobalVariable(self.llmodule, llty, name)
if llvalue is not None:
llglobal.linkage = "private"
llglobal.initializer = llvalue
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):
typ, attr = insn.object().type, insn.attr
if types.is_tuple(typ):
@ -695,20 +709,24 @@ class LLVMIRGenerator:
else:
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:
llfun = self.llbuilder.load(self.get_closure(typ.constructor, attr))
llself = self.map(insn.object())
llmethodty = self.llty_of_type(insn.type)
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__'))
llmethod = self.llbuilder.insert_value(llmethod, self.map(insn.object()),
llmethod = self.llbuilder.insert_value(llmethod, llself,
self.attr_index(insn.type, '__self__'))
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:
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):
typ, attr = insn.object().type, insn.attr
@ -722,6 +740,10 @@ class LLVMIRGenerator:
else:
assert False
if types.is_function(insn.value().type) and attr in typ.attributes and \
types.is_constructor(typ):
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)