mirror of https://github.com/m-labs/artiq.git
llvm_ir_generator: update debug info emission for LLVM 3.8.
This commit is contained in:
parent
132b55d6be
commit
b1f371e578
|
@ -42,126 +42,89 @@ def memoize(generator):
|
||||||
class DebugInfoEmitter:
|
class DebugInfoEmitter:
|
||||||
def __init__(self, llmodule):
|
def __init__(self, llmodule):
|
||||||
self.llmodule = llmodule
|
self.llmodule = llmodule
|
||||||
|
self.llsubprograms = []
|
||||||
self.cache = {}
|
self.cache = {}
|
||||||
self.subprograms = []
|
|
||||||
|
|
||||||
def emit(self, operands):
|
def emit_metadata(self, operands):
|
||||||
def map_operand(operand):
|
def map_operand(operand):
|
||||||
if operand is None:
|
if operand is None:
|
||||||
return ll.Constant(llmetadata, None)
|
return ll.Constant(llmetadata, None)
|
||||||
elif isinstance(operand, str):
|
elif isinstance(operand, str):
|
||||||
return ll.MetaDataString(self.llmodule, operand)
|
return ll.MetaDataString(self.llmodule, operand)
|
||||||
elif isinstance(operand, bool):
|
|
||||||
return ll.Constant(lli1, operand)
|
|
||||||
elif isinstance(operand, int):
|
elif isinstance(operand, int):
|
||||||
return ll.Constant(lli32, operand)
|
return ll.Constant(lli32, operand)
|
||||||
elif isinstance(operand, (list, tuple)):
|
elif isinstance(operand, (list, tuple)):
|
||||||
return self.emit(operand)
|
return self.emit_metadata(operand)
|
||||||
elif isinstance(operand, ll.Value):
|
|
||||||
return operand
|
|
||||||
else:
|
else:
|
||||||
print(operand)
|
assert isinstance(operand, ll.NamedValue)
|
||||||
assert False
|
return operand
|
||||||
return self.llmodule.add_metadata(list(map(map_operand, operands)))
|
return self.llmodule.add_metadata(list(map(map_operand, operands)))
|
||||||
|
|
||||||
@memoize
|
def emit_debug_info(self, kind, operands, is_distinct=False):
|
||||||
def emit_filename(self, source_buffer):
|
return self.llmodule.add_debug_info(kind, operands, is_distinct)
|
||||||
source_dir, source_file = os.path.split(source_buffer.name)
|
|
||||||
return self.emit([source_file, source_dir])
|
|
||||||
|
|
||||||
@memoize
|
|
||||||
def emit_compile_unit(self, source_buffer, llsubprograms):
|
|
||||||
return self.emit([
|
|
||||||
DW_TAG_compile_unit,
|
|
||||||
self.emit_filename(source_buffer), # filename
|
|
||||||
DW_LANG_Python, # source language
|
|
||||||
"ARTIQ", # producer
|
|
||||||
False, # optimized?
|
|
||||||
"", # linker flags
|
|
||||||
0, # runtime version
|
|
||||||
[], # enum types
|
|
||||||
[], # retained types
|
|
||||||
llsubprograms, # subprograms
|
|
||||||
[], # global variables
|
|
||||||
[], # imported entities
|
|
||||||
"", # split debug filename
|
|
||||||
2, # kind (full=1, lines only=2)
|
|
||||||
])
|
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
def emit_file(self, source_buffer):
|
def emit_file(self, source_buffer):
|
||||||
return self.emit([
|
source_dir, source_file = os.path.split(source_buffer.name)
|
||||||
DW_TAG_file_type,
|
return self.emit_debug_info("DIFile", {
|
||||||
self.emit_filename(source_buffer), # filename
|
"filename": source_file,
|
||||||
])
|
"directory": source_dir,
|
||||||
|
})
|
||||||
|
|
||||||
|
@memoize
|
||||||
|
def emit_compile_unit(self, source_buffer, llsubprograms):
|
||||||
|
return self.emit_debug_info("DICompileUnit", {
|
||||||
|
"language": ll.DIToken("DW_LANG_C99"),
|
||||||
|
"file": self.emit_file(source_buffer),
|
||||||
|
"producer": "ARTIQ",
|
||||||
|
"runtimeVersion": 0,
|
||||||
|
"emissionKind": 2, # full=1, lines only=2
|
||||||
|
"subprograms": self.emit_metadata(llsubprograms)
|
||||||
|
}, is_distinct=True)
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
def emit_subroutine_type(self, typ):
|
def emit_subroutine_type(self, typ):
|
||||||
return self.emit([
|
return self.emit_debug_info("DISubroutineType", {
|
||||||
DW_TAG_subroutine_type,
|
"types": self.emit_metadata([None])
|
||||||
None, # filename
|
})
|
||||||
None, # context descriptor
|
|
||||||
"", # name
|
|
||||||
0, # line number
|
|
||||||
0, # (i64) size in bits
|
|
||||||
0, # (i64) alignment in bits
|
|
||||||
0, # (i64) offset in bits
|
|
||||||
0, # flags
|
|
||||||
None, # derived from
|
|
||||||
[None], # members
|
|
||||||
0, # runtime languages
|
|
||||||
None, # base type with vtable pointer
|
|
||||||
None, # template parameters
|
|
||||||
None # unique identifier
|
|
||||||
])
|
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
def emit_subprogram(self, func, llfunc):
|
def emit_subprogram(self, func, llfunc):
|
||||||
source_buffer = func.loc.source_buffer
|
source_buffer = func.loc.source_buffer
|
||||||
display_name = "{}{}".format(func.name, types.TypePrinter().name(func.type))
|
display_name = "{}{}".format(func.name, types.TypePrinter().name(func.type))
|
||||||
subprogram = self.emit([
|
llsubprogram = self.emit_debug_info("DISubprogram", {
|
||||||
DW_TAG_subprogram,
|
"name": func.name,
|
||||||
self.emit_filename(source_buffer), # filename
|
"linkageName": llfunc.name,
|
||||||
self.emit_file(source_buffer), # context descriptor
|
"type": self.emit_subroutine_type(func.type),
|
||||||
func.name, # name
|
"file": self.emit_file(source_buffer),
|
||||||
display_name, # display name
|
"line": func.loc.line(),
|
||||||
llfunc.name, # linkage name
|
"scope": self.emit_file(source_buffer),
|
||||||
func.loc.line(), # line number where defined
|
"scopeLine": func.loc.line(),
|
||||||
self.emit_subroutine_type(func.type), # type descriptor
|
"isLocal": func.is_internal,
|
||||||
func.is_internal, # local to compile unit?
|
"isDefinition": True,
|
||||||
True, # global is defined in the compile unit?
|
"variables": self.emit_metadata([])
|
||||||
0, # virtuality
|
}, is_distinct=True)
|
||||||
0, # index into a virtual function
|
self.llsubprograms.append(llsubprogram)
|
||||||
None, # base type with vtable pointer
|
return llsubprogram
|
||||||
0, # flags
|
|
||||||
False, # optimized?
|
|
||||||
llfunc, # LLVM function
|
|
||||||
None, # template parameters
|
|
||||||
None, # function declaration descriptor
|
|
||||||
[], # function variables
|
|
||||||
func.loc.line(), # line number where scope begins
|
|
||||||
])
|
|
||||||
self.subprograms.append(subprogram)
|
|
||||||
return subprogram
|
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
def emit_loc(self, loc, scope, inlined_scope=None):
|
def emit_loc(self, loc, scope):
|
||||||
return self.emit([
|
return self.emit_debug_info("DILocation", {
|
||||||
loc.line(), # line
|
"line": loc.line(),
|
||||||
loc.column(), # column
|
"column": loc.column(),
|
||||||
scope, # scope
|
"scope": scope
|
||||||
inlined_scope, # inlined scope
|
})
|
||||||
])
|
|
||||||
|
|
||||||
def finalize(self, source_buffer):
|
def finalize(self, source_buffer):
|
||||||
llident = self.llmodule.add_named_metadata('llvm.ident')
|
llident = self.llmodule.add_named_metadata('llvm.ident')
|
||||||
llident.add(self.emit(["ARTIQ"]))
|
llident.add(self.emit_metadata(["ARTIQ"]))
|
||||||
|
|
||||||
llflags = self.llmodule.add_named_metadata('llvm.module.flags')
|
llflags = self.llmodule.add_named_metadata('llvm.module.flags')
|
||||||
llflags.add(self.emit([2, "Debug Info Version", 1]))
|
llflags.add(self.emit_metadata([2, "Debug Info Version", 3]))
|
||||||
|
llflags.add(self.emit_metadata([2, "Dwarf Version", 4]))
|
||||||
|
|
||||||
llcompile_units = self.llmodule.add_named_metadata('llvm.dbg.cu')
|
llcompile_units = self.llmodule.add_named_metadata('llvm.dbg.cu')
|
||||||
llcompile_units.add(self.emit_compile_unit(source_buffer, tuple(self.subprograms)))
|
llcompile_units.add(self.emit_compile_unit(source_buffer, tuple(self.llsubprograms)))
|
||||||
|
|
||||||
|
|
||||||
class LLVMIRGenerator:
|
class LLVMIRGenerator:
|
||||||
|
@ -578,6 +541,7 @@ class LLVMIRGenerator:
|
||||||
llblock_map = {}
|
llblock_map = {}
|
||||||
|
|
||||||
disubprogram = self.debug_info_emitter.emit_subprogram(func, self.llfunction)
|
disubprogram = self.debug_info_emitter.emit_subprogram(func, self.llfunction)
|
||||||
|
self.llfunction.set_metadata('dbg', disubprogram)
|
||||||
|
|
||||||
# First, map arguments.
|
# First, map arguments.
|
||||||
if self.has_sret(func.type):
|
if self.has_sret(func.type):
|
||||||
|
@ -683,15 +647,15 @@ class LLVMIRGenerator:
|
||||||
llptr = self.llbuilder.gep(llenv, [self.llindex(0), self.llindex(outer_index)],
|
llptr = self.llbuilder.gep(llenv, [self.llindex(0), self.llindex(outer_index)],
|
||||||
inbounds=True)
|
inbounds=True)
|
||||||
llouterenv = self.llbuilder.load(llptr)
|
llouterenv = self.llbuilder.load(llptr)
|
||||||
llouterenv.metadata['invariant.load'] = self.empty_metadata
|
llouterenv.set_metadata('invariant.load', self.empty_metadata)
|
||||||
llouterenv.metadata['nonnull'] = self.empty_metadata
|
llouterenv.set_metadata('nonnull', self.empty_metadata)
|
||||||
return self.llptr_to_var(llouterenv, env_ty.params["$outer"], var_name)
|
return self.llptr_to_var(llouterenv, env_ty.params["$outer"], var_name)
|
||||||
|
|
||||||
def mark_dereferenceable(self, load):
|
def mark_dereferenceable(self, load):
|
||||||
assert isinstance(load, ll.LoadInstr) and isinstance(load.type, ll.PointerType)
|
assert isinstance(load, ll.LoadInstr) and isinstance(load.type, ll.PointerType)
|
||||||
pointee_size = load.type.pointee.get_abi_size(self.lldatalayout, context=self.llcontext)
|
pointee_size = load.type.pointee.get_abi_size(self.lldatalayout, context=self.llcontext)
|
||||||
metadata = self.llmodule.add_metadata([ll.Constant(lli64, pointee_size)])
|
metadata = self.llmodule.add_metadata([ll.Constant(lli64, pointee_size)])
|
||||||
load.metadata['dereferenceable'] = metadata
|
load.set_metadata('dereferenceable', metadata)
|
||||||
|
|
||||||
def process_GetLocal(self, insn):
|
def process_GetLocal(self, insn):
|
||||||
env = insn.environment()
|
env = insn.environment()
|
||||||
|
@ -821,7 +785,7 @@ class LLVMIRGenerator:
|
||||||
inbounds=True, name="ptr.{}".format(insn.name))
|
inbounds=True, name="ptr.{}".format(insn.name))
|
||||||
llvalue = self.llbuilder.load(llptr, name="val.{}".format(insn.name))
|
llvalue = self.llbuilder.load(llptr, name="val.{}".format(insn.name))
|
||||||
if types.is_instance(typ) and attr in typ.constant_attributes:
|
if types.is_instance(typ) and attr in typ.constant_attributes:
|
||||||
llvalue.metadata['invariant.load'] = self.empty_metadata
|
llvalue.set_metadata('invariant.load', self.empty_metadata)
|
||||||
if isinstance(llvalue.type, ll.PointerType):
|
if isinstance(llvalue.type, ll.PointerType):
|
||||||
self.mark_dereferenceable(llvalue)
|
self.mark_dereferenceable(llvalue)
|
||||||
return llvalue
|
return llvalue
|
||||||
|
@ -1065,8 +1029,8 @@ class LLVMIRGenerator:
|
||||||
llptr = self.llbuilder.gep(llenv, [self.llindex(0), self.llindex(outer_index)],
|
llptr = self.llbuilder.gep(llenv, [self.llindex(0), self.llindex(outer_index)],
|
||||||
inbounds=True)
|
inbounds=True)
|
||||||
llouterenv = self.llbuilder.load(llptr)
|
llouterenv = self.llbuilder.load(llptr)
|
||||||
llouterenv.metadata['invariant.load'] = self.empty_metadata
|
llouterenv.set_metadata('invariant.load', self.empty_metadata)
|
||||||
llouterenv.metadata['nonnull'] = self.empty_metadata
|
llouterenv.set_metadata('nonnull', self.empty_metadata)
|
||||||
return self.llptr_to_var(llouterenv, env_ty.params["$outer"], var_name)
|
return self.llptr_to_var(llouterenv, env_ty.params["$outer"], var_name)
|
||||||
else:
|
else:
|
||||||
return llenv
|
return llenv
|
||||||
|
@ -1325,7 +1289,7 @@ class LLVMIRGenerator:
|
||||||
# Never add TBAA nowrite metadata to a functon with sret!
|
# Never add TBAA nowrite metadata to a functon with sret!
|
||||||
# This leads to miscompilations.
|
# This leads to miscompilations.
|
||||||
if types.is_c_function(functiontyp) and 'nowrite' in functiontyp.flags:
|
if types.is_c_function(functiontyp) and 'nowrite' in functiontyp.flags:
|
||||||
llcall.metadata['tbaa'] = self.tbaa_nowrite_call
|
llcall.set_metadata('tbaa', self.tbaa_nowrite_call)
|
||||||
|
|
||||||
return llresult
|
return llresult
|
||||||
|
|
||||||
|
@ -1358,7 +1322,7 @@ class LLVMIRGenerator:
|
||||||
|
|
||||||
# See the comment in process_Call.
|
# See the comment in process_Call.
|
||||||
if types.is_c_function(functiontyp) and 'nowrite' in functiontyp.flags:
|
if types.is_c_function(functiontyp) and 'nowrite' in functiontyp.flags:
|
||||||
llcall.metadata['tbaa'] = self.tbaa_nowrite_call
|
llcall.set_metadata('tbaa', self.tbaa_nowrite_call)
|
||||||
|
|
||||||
return llcall
|
return llcall
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue