Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: edb7423a4f24
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ee1ef551bc85
Choose a head ref
  • 3 commits
  • 2 files changed
  • 1 contributor

Commits on Jan 10, 2016

  1. transforms.llvm_ir_generator: use sret attribute.

    whitequark committed Jan 10, 2016
    Copy the full SHA
    7f914a0 View commit details
  2. Copy the full SHA
    d436093 View commit details
  3. Fix symbolizer invocation with no addresses.

    whitequark committed Jan 10, 2016
    Copy the full SHA
    ee1ef55 View commit details
Showing with 43 additions and 37 deletions.
  1. +3 −0 artiq/compiler/targets.py
  2. +40 −37 artiq/compiler/transforms/llvm_ir_generator.py
3 changes: 3 additions & 0 deletions artiq/compiler/targets.py
Original file line number Diff line number Diff line change
@@ -148,6 +148,9 @@ def strip(self, library):
return results["output"].read()

def symbolize(self, library, addresses):
if addresses == []:
return []

# Addresses point one instruction past the jump; offset them back by 1.
offset_addresses = [hex(addr - 1) for addr in addresses]
with RunTool([self.triple + "-addr2line", "--functions", "--inlines",
77 changes: 40 additions & 37 deletions artiq/compiler/transforms/llvm_ir_generator.py
Original file line number Diff line number Diff line change
@@ -193,6 +193,10 @@ def needs_sret(self, lltyp, may_be_large=True):
else:
return True

def has_sret(self, functy):
llretty = self.llty_of_type(functy.ret, for_return=True)
return self.needs_sret(llretty)

def llty_of_type(self, typ, bare=False, for_return=False):
typ = typ.find()
if types.is_tuple(typ):
@@ -219,22 +223,14 @@ def llty_of_type(self, typ, bare=False, for_return=False):
for arg in typ.optargs],
return_type=llretty)

# TODO: actually mark the first argument as sret (also noalias nocapture).
# llvmlite currently does not have support for this;
# https://github.com/numba/llvmlite/issues/91.
if sretarg:
llty.__has_sret = True
else:
llty.__has_sret = False

if bare:
return llty
else:
return ll.LiteralStructType([envarg, llty.as_pointer()])
elif types.is_method(typ):
llfuncty = self.llty_of_type(types.get_method_function(typ))
llfunty = self.llty_of_type(types.get_method_function(typ))
llselfty = self.llty_of_type(types.get_method_self(typ))
return ll.LiteralStructType([llfuncty, llselfty])
return ll.LiteralStructType([llfunty, llselfty])
elif builtins.is_none(typ):
if for_return:
return llvoid
@@ -400,8 +396,13 @@ def map(self, value):
elif isinstance(value, ir.Function):
llfun = self.llmodule.get_global(value.name)
if llfun is None:
llfun = ll.Function(self.llmodule, self.llty_of_type(value.type, bare=True),
value.name)
llfunty = self.llty_of_type(value.type, bare=True)
llfun = ll.Function(self.llmodule, llfunty, value.name)

llretty = self.llty_of_type(value.type.ret, for_return=True)
if self.needs_sret(llretty):
llfun.args[0].add_attribute('sret')

return llfun
else:
assert False
@@ -516,11 +517,7 @@ def rpc_tag_error(typ):

def process_function(self, func):
try:
self.llfunction = self.llmodule.get_global(func.name)

if self.llfunction is None:
llfunty = self.llty_of_type(func.type, bare=True)
self.llfunction = ll.Function(self.llmodule, llfunty, func.name)
self.llfunction = self.map(func)

if func.is_internal:
self.llfunction.linkage = 'internal'
@@ -533,7 +530,7 @@ def process_function(self, func):
disubprogram = self.debug_info_emitter.emit_subprogram(func, self.llfunction)

# First, map arguments.
if self.llfunction.type.pointee.__has_sret:
if self.has_sret(func.type):
llactualargs = self.llfunction.args[1:]
else:
llactualargs = self.llfunction.args
@@ -943,10 +940,17 @@ def _prepare_ffi_call(self, insn):
llfunname = insn.target_function().type.name
llfun = self.llmodule.get_global(llfunname)
if llfun is None:
llfunty = ll.FunctionType(self.llty_of_type(insn.type, for_return=True),
[llarg.type for llarg in llargs])
llfun = ll.Function(self.llmodule, llfunty,
insn.target_function().type.name)
llretty = self.llty_of_type(insn.type, for_return=True)
if self.needs_sret(llretty):
llfunty = ll.FunctionType(llvoid, [llretty.as_pointer()] +
[llarg.type for llarg in llargs])
else:
llfunty = ll.FunctionType(llretty, [llarg.type for llarg in llargs])

llfun = ll.Function(self.llmodule, llfunty,
insn.target_function().type.name)
if self.needs_sret(llretty):
llfun.args[0].add_attribute('sret')
return llfun, list(llargs)

# See session.c:{send,receive}_rpc_value and comm_generic.py:_{send,receive}_rpc_value.
@@ -1090,24 +1094,22 @@ def process_Call(self, insn):
llnormalblock=None, llunwindblock=None)
elif types.is_c_function(insn.target_function().type):
llfun, llargs = self._prepare_ffi_call(insn)
return self.llbuilder.call(llfun, llargs,
name=insn.name)
else:
llfun, llargs = self._prepare_closure_call(insn)

if llfun.type.pointee.__has_sret:
llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), [])
if self.has_sret(insn.target_function().type):
llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), [])

llresultslot = self.llbuilder.alloca(llfun.type.pointee.args[0].pointee)
self.llbuilder.call(llfun, [llresultslot] + llargs)
llresult = self.llbuilder.load(llresultslot)
llresultslot = self.llbuilder.alloca(llfun.type.pointee.args[0].pointee)
self.llbuilder.call(llfun, [llresultslot] + llargs)
llresult = self.llbuilder.load(llresultslot)

self.llbuilder.call(self.llbuiltin("llvm.stackrestore"), [llstackptr])
self.llbuilder.call(self.llbuiltin("llvm.stackrestore"), [llstackptr])

return llresult
else:
return self.llbuilder.call(llfun, llargs,
name=insn.name)
return llresult
else:
return self.llbuilder.call(llfun, llargs,
name=insn.name)

def process_Invoke(self, insn):
llnormalblock = self.map(insn.normal_target())
@@ -1221,11 +1223,12 @@ def process_Return(self, insn):
if builtins.is_none(insn.value().type):
return self.llbuilder.ret_void()
else:
if self.llfunction.type.pointee.__has_sret:
self.llbuilder.store(self.map(insn.value()), self.llfunction.args[0])
llvalue = self.map(insn.value())
if self.needs_sret(llvalue):
self.llbuilder.store(llvalue, self.llfunction.args[0])
return self.llbuilder.ret_void()
else:
return self.llbuilder.ret(self.map(insn.value()))
return self.llbuilder.ret(llvalue)

def process_Unreachable(self, insn):
return self.llbuilder.unreachable()