forked from M-Labs/artiq
compiler/transforms/llvm_ir_generator: changed list representation
The representation of TList(T) is changed from `{T*, u32}` to `{T*, u32}*`. The old representation forbids changing the length of a list when the list is passed as a parameter into functions, as the length is passed by value. The representation now matches with nac3.
This commit is contained in:
parent
8415151866
commit
eb6817c8f1
|
@ -253,7 +253,10 @@ class LLVMIRGenerator:
|
||||||
return ll.LiteralStructType([llbufferty, llshapety])
|
return ll.LiteralStructType([llbufferty, llshapety])
|
||||||
elif builtins.is_listish(typ):
|
elif builtins.is_listish(typ):
|
||||||
lleltty = self.llty_of_type(builtins.get_iterable_elt(typ))
|
lleltty = self.llty_of_type(builtins.get_iterable_elt(typ))
|
||||||
return ll.LiteralStructType([lleltty.as_pointer(), lli32])
|
lltyp = ll.LiteralStructType([lleltty.as_pointer(), lli32])
|
||||||
|
if builtins.is_list(typ):
|
||||||
|
lltyp = lltyp.as_pointer()
|
||||||
|
return lltyp
|
||||||
elif builtins.is_range(typ):
|
elif builtins.is_range(typ):
|
||||||
lleltty = self.llty_of_type(builtins.get_iterable_elt(typ))
|
lleltty = self.llty_of_type(builtins.get_iterable_elt(typ))
|
||||||
return ll.LiteralStructType([lleltty, lleltty, lleltty])
|
return ll.LiteralStructType([lleltty, lleltty, lleltty])
|
||||||
|
@ -782,8 +785,19 @@ class LLVMIRGenerator:
|
||||||
llalloc = self.llbuilder.alloca(lleltty, size=llsize)
|
llalloc = self.llbuilder.alloca(lleltty, size=llsize)
|
||||||
if types._is_pointer(insn.type):
|
if types._is_pointer(insn.type):
|
||||||
return llalloc
|
return llalloc
|
||||||
|
if builtins.is_list(insn.type):
|
||||||
|
llvalue = self.llbuilder.alloca(self.llty_of_type(insn.type).pointee, size=1)
|
||||||
|
self.llbuilder.store(llalloc, self.llbuilder.gep(llvalue,
|
||||||
|
[self.llindex(0),
|
||||||
|
self.llindex(0)],
|
||||||
|
inbounds=True))
|
||||||
|
self.llbuilder.store(llsize, self.llbuilder.gep(llvalue,
|
||||||
|
[self.llindex(0),
|
||||||
|
self.llindex(1)],
|
||||||
|
inbounds=True))
|
||||||
|
else:
|
||||||
llvalue = ll.Constant(self.llty_of_type(insn.type), ll.Undefined)
|
llvalue = ll.Constant(self.llty_of_type(insn.type), ll.Undefined)
|
||||||
llvalue = self.llbuilder.insert_value(llvalue, llalloc, 0, name=insn.name)
|
llvalue = self.llbuilder.insert_value(llvalue, llalloc, 0)
|
||||||
llvalue = self.llbuilder.insert_value(llvalue, llsize, 1)
|
llvalue = self.llbuilder.insert_value(llvalue, llsize, 1)
|
||||||
return llvalue
|
return llvalue
|
||||||
elif (not builtins.is_allocated(insn.type) or ir.is_keyword(insn.type)
|
elif (not builtins.is_allocated(insn.type) or ir.is_keyword(insn.type)
|
||||||
|
@ -988,8 +1002,14 @@ class LLVMIRGenerator:
|
||||||
def process_Offset(self, insn):
|
def process_Offset(self, insn):
|
||||||
base, idx = insn.base(), insn.index()
|
base, idx = insn.base(), insn.index()
|
||||||
llelts, llidx = map(self.map, (base, idx))
|
llelts, llidx = map(self.map, (base, idx))
|
||||||
if not types._is_pointer(base.type):
|
if builtins.is_listish(base.type):
|
||||||
# This is list-ish.
|
# This is list-ish.
|
||||||
|
if builtins.is_list(base.type):
|
||||||
|
llelts = self.llbuilder.load(self.llbuilder.gep(llelts,
|
||||||
|
[self.llindex(0),
|
||||||
|
self.llindex(0)],
|
||||||
|
inbounds=True))
|
||||||
|
else:
|
||||||
llelts = self.llbuilder.extract_value(llelts, 0)
|
llelts = self.llbuilder.extract_value(llelts, 0)
|
||||||
llelt = self.llbuilder.gep(llelts, [llidx], inbounds=True)
|
llelt = self.llbuilder.gep(llelts, [llidx], inbounds=True)
|
||||||
return llelt
|
return llelt
|
||||||
|
@ -1004,8 +1024,14 @@ class LLVMIRGenerator:
|
||||||
def process_SetElem(self, insn):
|
def process_SetElem(self, insn):
|
||||||
base, idx = insn.base(), insn.index()
|
base, idx = insn.base(), insn.index()
|
||||||
llelts, llidx = map(self.map, (base, idx))
|
llelts, llidx = map(self.map, (base, idx))
|
||||||
if not types._is_pointer(base.type):
|
if builtins.is_listish(base.type):
|
||||||
# This is list-ish.
|
# This is list-ish.
|
||||||
|
if builtins.is_list(base.type):
|
||||||
|
llelts = self.llbuilder.load(self.llbuilder.gep(llelts,
|
||||||
|
[self.llindex(0),
|
||||||
|
self.llindex(0)],
|
||||||
|
inbounds=True))
|
||||||
|
else:
|
||||||
llelts = self.llbuilder.extract_value(llelts, 0)
|
llelts = self.llbuilder.extract_value(llelts, 0)
|
||||||
llelt = self.llbuilder.gep(llelts, [llidx], inbounds=True)
|
llelt = self.llbuilder.gep(llelts, [llidx], inbounds=True)
|
||||||
return self.llbuilder.store(self.map(insn.value()), llelt)
|
return self.llbuilder.store(self.map(insn.value()), llelt)
|
||||||
|
@ -1152,6 +1178,11 @@ class LLVMIRGenerator:
|
||||||
lllhs, llrhs = map(self.map, (insn.lhs(), insn.rhs()))
|
lllhs, llrhs = map(self.map, (insn.lhs(), insn.rhs()))
|
||||||
assert lllhs.type == llrhs.type
|
assert lllhs.type == llrhs.type
|
||||||
|
|
||||||
|
if isinstance(lllhs.type, ll.PointerType) and \
|
||||||
|
isinstance(lllhs.type.pointee, ll.LiteralStructType):
|
||||||
|
lllhs = self.llbuilder.load(lllhs)
|
||||||
|
llrhs = self.llbuilder.load(llrhs)
|
||||||
|
|
||||||
if isinstance(lllhs.type, ll.IntType):
|
if isinstance(lllhs.type, ll.IntType):
|
||||||
return self.llbuilder.icmp_signed(op, lllhs, llrhs,
|
return self.llbuilder.icmp_signed(op, lllhs, llrhs,
|
||||||
name=insn.name)
|
name=insn.name)
|
||||||
|
@ -1222,6 +1253,11 @@ class LLVMIRGenerator:
|
||||||
shape = self.llbuilder.extract_value(self.map(collection),
|
shape = self.llbuilder.extract_value(self.map(collection),
|
||||||
self.attr_index(collection.type, "shape"))
|
self.attr_index(collection.type, "shape"))
|
||||||
return self.llbuilder.extract_value(shape, 0)
|
return self.llbuilder.extract_value(shape, 0)
|
||||||
|
elif builtins.is_list(collection.type):
|
||||||
|
return self.llbuilder.load(self.llbuilder.gep(self.map(collection),
|
||||||
|
[self.llindex(0),
|
||||||
|
self.llindex(1)]))
|
||||||
|
else:
|
||||||
return self.llbuilder.extract_value(self.map(collection), 1)
|
return self.llbuilder.extract_value(self.map(collection), 1)
|
||||||
elif insn.op in ("printf", "rtio_log"):
|
elif insn.op in ("printf", "rtio_log"):
|
||||||
# We only get integers, floats, pointers and strings here.
|
# We only get integers, floats, pointers and strings here.
|
||||||
|
@ -1677,6 +1713,13 @@ class LLVMIRGenerator:
|
||||||
assert isinstance(value, (list, numpy.ndarray)), fail_msg
|
assert isinstance(value, (list, numpy.ndarray)), fail_msg
|
||||||
elt_type = builtins.get_iterable_elt(typ)
|
elt_type = builtins.get_iterable_elt(typ)
|
||||||
lleltsptr = self._quote_listish_to_llglobal(value, elt_type, path, typ.find().name)
|
lleltsptr = self._quote_listish_to_llglobal(value, elt_type, path, typ.find().name)
|
||||||
|
if builtins.is_list(typ):
|
||||||
|
llconst = ll.Constant(llty.pointee, [lleltsptr, ll.Constant(lli32, len(value))])
|
||||||
|
name = self.llmodule.scope.deduplicate("quoted.{}".format(typ.find().name))
|
||||||
|
llglobal = ll.GlobalVariable(self.llmodule, llconst.type, name)
|
||||||
|
llglobal.initializer = llconst
|
||||||
|
llglobal.linkage = "private"
|
||||||
|
return llglobal
|
||||||
llconst = ll.Constant(llty, [lleltsptr, ll.Constant(lli32, len(value))])
|
llconst = ll.Constant(llty, [lleltsptr, ll.Constant(lli32, len(value))])
|
||||||
return llconst
|
return llconst
|
||||||
elif types.is_tuple(typ):
|
elif types.is_tuple(typ):
|
||||||
|
|
Loading…
Reference in New Issue