@@ -92,6 +92,7 @@ type Frame struct {
9292 taskHandle llvm.Value
9393 deferPtr llvm.Value
9494 difunc llvm.Metadata
95+ dilocals map [* types.Var ]llvm.Metadata
9596 allDeferFuncs []interface {}
9697 deferFuncs map [* ir.Function ]int
9798 deferInvokeFuncs map [string ]int
@@ -708,10 +709,51 @@ func (c *Compiler) createDIType(typ types.Type) llvm.Metadata {
708709 }
709710}
710711
712+ // getLocalVariable returns a debug info entry for a local variable, which may
713+ // either be a parameter or a regular variable. It will create a new metadata
714+ // entry if there isn't one for the variable yet.
715+ func (c * Compiler ) getLocalVariable (frame * Frame , variable * types.Var ) llvm.Metadata {
716+ if dilocal , ok := frame .dilocals [variable ]; ok {
717+ // DILocalVariable was already created, return it directly.
718+ return dilocal
719+ }
720+
721+ pos := c .ir .Program .Fset .Position (variable .Pos ())
722+
723+ // Check whether this is a function parameter.
724+ for i , param := range frame .fn .Params {
725+ if param .Object ().(* types.Var ) == variable {
726+ // Yes it is, create it as a function parameter.
727+ dilocal := c .dibuilder .CreateParameterVariable (frame .difunc , llvm.DIParameterVariable {
728+ Name : param .Name (),
729+ File : c .getDIFile (pos .Filename ),
730+ Line : pos .Line ,
731+ Type : c .getDIType (variable .Type ()),
732+ AlwaysPreserve : true ,
733+ ArgNo : i + 1 ,
734+ })
735+ frame .dilocals [variable ] = dilocal
736+ return dilocal
737+ }
738+ }
739+
740+ // No, it's not a parameter. Create a regular (auto) variable.
741+ dilocal := c .dibuilder .CreateAutoVariable (frame .difunc , llvm.DIAutoVariable {
742+ Name : variable .Name (),
743+ File : c .getDIFile (pos .Filename ),
744+ Line : pos .Line ,
745+ Type : c .getDIType (variable .Type ()),
746+ AlwaysPreserve : true ,
747+ })
748+ frame .dilocals [variable ] = dilocal
749+ return dilocal
750+ }
751+
711752func (c * Compiler ) parseFuncDecl (f * ir.Function ) * Frame {
712753 frame := & Frame {
713754 fn : f ,
714755 locals : make (map [ssa.Value ]llvm.Value ),
756+ dilocals : make (map [* types.Var ]llvm.Metadata ),
715757 blockEntries : make (map [* ssa.BasicBlock ]llvm.BasicBlock ),
716758 blockExits : make (map [* ssa.BasicBlock ]llvm.BasicBlock ),
717759 }
@@ -783,11 +825,11 @@ func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix,
783825 diparams = append (diparams , c .getDIType (param .Type ()))
784826 }
785827 diFuncType := c .dibuilder .CreateSubroutineType (llvm.DISubroutineType {
786- File : c .difiles [ filename ] ,
828+ File : c .getDIFile ( filename ) ,
787829 Parameters : diparams ,
788830 Flags : 0 , // ?
789831 })
790- difunc := c .dibuilder .CreateFunction (c .difiles [ filename ] , llvm.DIFunction {
832+ difunc := c .dibuilder .CreateFunction (c .getDIFile ( filename ) , llvm.DIFunction {
791833 Name : f .RelString (nil ) + suffix ,
792834 LinkageName : f .LinkName () + suffix ,
793835 File : c .getDIFile (filename ),
@@ -872,7 +914,7 @@ func (c *Compiler) parseFunc(frame *Frame) {
872914
873915 // Load function parameters
874916 llvmParamIndex := 0
875- for i , param := range frame .fn .Params {
917+ for _ , param := range frame .fn .Params {
876918 llvmType := c .getLLVMType (param .Type ())
877919 fields := make ([]llvm.Value , 0 , 1 )
878920 for range c .expandFormalParamType (llvmType ) {
@@ -883,16 +925,7 @@ func (c *Compiler) parseFunc(frame *Frame) {
883925
884926 // Add debug information to this parameter (if available)
885927 if c .Debug () && frame .fn .Syntax () != nil {
886- pos := c .ir .Program .Fset .Position (frame .fn .Syntax ().Pos ())
887- diType := c .getDIType (param .Type ())
888- dbgParam := c .dibuilder .CreateParameterVariable (frame .difunc , llvm.DIParameterVariable {
889- Name : param .Name (),
890- File : c .difiles [pos .Filename ],
891- Line : pos .Line ,
892- Type : diType ,
893- AlwaysPreserve : true ,
894- ArgNo : i + 1 ,
895- })
928+ dbgParam := c .getLocalVariable (frame , param .Object ().(* types.Var ))
896929 loc := c .builder .GetCurrentDebugLocation ()
897930 if len (fields ) == 1 {
898931 expr := c .dibuilder .CreateExpression (nil )
@@ -950,7 +983,28 @@ func (c *Compiler) parseFunc(frame *Frame) {
950983 c .builder .SetInsertPointAtEnd (frame .blockEntries [block ])
951984 frame .currentBlock = block
952985 for _ , instr := range block .Instrs {
953- if _ , ok := instr .(* ssa.DebugRef ); ok {
986+ if instr , ok := instr .(* ssa.DebugRef ); ok {
987+ if ! c .Debug () {
988+ continue
989+ }
990+ object := instr .Object ()
991+ variable , ok := object .(* types.Var )
992+ if ! ok {
993+ // Not a local variable.
994+ continue
995+ }
996+ if instr .IsAddr {
997+ // TODO, this may happen for *ssa.Alloc and *ssa.FieldAddr
998+ // for example.
999+ continue
1000+ }
1001+ dbgVar := c .getLocalVariable (frame , variable )
1002+ pos := c .ir .Program .Fset .Position (instr .Pos ())
1003+ c .dibuilder .InsertValueAtEnd (c .getValue (frame , instr .X ), dbgVar , c .dibuilder .CreateExpression (nil ), llvm.DebugLoc {
1004+ Line : uint (pos .Line ),
1005+ Col : uint (pos .Column ),
1006+ Scope : frame .difunc ,
1007+ }, c .builder .GetInsertBlock ())
9541008 continue
9551009 }
9561010 if c .DumpSSA () {
0 commit comments