@@ -297,7 +297,7 @@ func (c *Compiler) Compile(mainPath string) []error {
297297 if frame .fn .Blocks == nil {
298298 continue // external function
299299 }
300- c . parseFunc ( frame )
300+ frame . createFunctionDefinition ( )
301301 }
302302
303303 // After all packages are imported, add a synthetic initializer function
@@ -689,40 +689,40 @@ func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
689689// getLocalVariable returns a debug info entry for a local variable, which may
690690// either be a parameter or a regular variable. It will create a new metadata
691691// entry if there isn't one for the variable yet.
692- func (c * Compiler ) getLocalVariable (frame * Frame , variable * types.Var ) llvm.Metadata {
693- if dilocal , ok := frame .dilocals [variable ]; ok {
692+ func (b * builder ) getLocalVariable (variable * types.Var ) llvm.Metadata {
693+ if dilocal , ok := b .dilocals [variable ]; ok {
694694 // DILocalVariable was already created, return it directly.
695695 return dilocal
696696 }
697697
698- pos := c .ir .Program .Fset .Position (variable .Pos ())
698+ pos := b .ir .Program .Fset .Position (variable .Pos ())
699699
700700 // Check whether this is a function parameter.
701- for i , param := range frame .fn .Params {
701+ for i , param := range b .fn .Params {
702702 if param .Object ().(* types.Var ) == variable {
703703 // Yes it is, create it as a function parameter.
704- dilocal := c .dibuilder .CreateParameterVariable (frame .difunc , llvm.DIParameterVariable {
704+ dilocal := b .dibuilder .CreateParameterVariable (b .difunc , llvm.DIParameterVariable {
705705 Name : param .Name (),
706- File : c .getDIFile (pos .Filename ),
706+ File : b .getDIFile (pos .Filename ),
707707 Line : pos .Line ,
708- Type : c .getDIType (variable .Type ()),
708+ Type : b .getDIType (variable .Type ()),
709709 AlwaysPreserve : true ,
710710 ArgNo : i + 1 ,
711711 })
712- frame .dilocals [variable ] = dilocal
712+ b .dilocals [variable ] = dilocal
713713 return dilocal
714714 }
715715 }
716716
717717 // No, it's not a parameter. Create a regular (auto) variable.
718- dilocal := c .dibuilder .CreateAutoVariable (frame .difunc , llvm.DIAutoVariable {
718+ dilocal := b .dibuilder .CreateAutoVariable (b .difunc , llvm.DIAutoVariable {
719719 Name : variable .Name (),
720- File : c .getDIFile (pos .Filename ),
720+ File : b .getDIFile (pos .Filename ),
721721 Line : pos .Line ,
722- Type : c .getDIType (variable .Type ()),
722+ Type : b .getDIType (variable .Type ()),
723723 AlwaysPreserve : true ,
724724 })
725- frame .dilocals [variable ] = dilocal
725+ b .dilocals [variable ] = dilocal
726726 return dilocal
727727}
728728
@@ -845,86 +845,89 @@ func (c *compilerContext) getDIFile(filename string) llvm.Metadata {
845845 return c .difiles [filename ]
846846}
847847
848- func (c * Compiler ) parseFunc (frame * Frame ) {
849- if c .DumpSSA () {
850- fmt .Printf ("\n func %s:\n " , frame .fn .Function )
848+ // createFunctionDefinition builds the LLVM IR implementation for this function.
849+ // The function must be declared but not yet defined, otherwise this function
850+ // will create a diagnostic.
851+ func (b * builder ) createFunctionDefinition () {
852+ if b .DumpSSA () {
853+ fmt .Printf ("\n func %s:\n " , b .fn .Function )
851854 }
852- if ! frame .fn .LLVMFn .IsDeclaration () {
853- errValue := frame .fn . LLVMFn .Name () + " redeclared in this program"
854- fnPos := getPosition (frame .fn .LLVMFn )
855+ if ! b .fn .LLVMFn .IsDeclaration () {
856+ errValue := b .fn .Name () + " redeclared in this program"
857+ fnPos := getPosition (b .fn .LLVMFn )
855858 if fnPos .IsValid () {
856859 errValue += "\n \t previous declaration at " + fnPos .String ()
857860 }
858- c .addError (frame .fn .Pos (), errValue )
861+ b .addError (b .fn .Pos (), errValue )
859862 return
860863 }
861- if ! frame .fn .IsExported () {
862- frame .fn .LLVMFn .SetLinkage (llvm .InternalLinkage )
863- frame .fn .LLVMFn .SetUnnamedAddr (true )
864+ if ! b .fn .IsExported () {
865+ b .fn .LLVMFn .SetLinkage (llvm .InternalLinkage )
866+ b .fn .LLVMFn .SetUnnamedAddr (true )
864867 }
865868
866869 // Some functions have a pragma controlling the inlining level.
867- switch frame .fn .Inline () {
870+ switch b .fn .Inline () {
868871 case ir .InlineHint :
869872 // Add LLVM inline hint to functions with //go:inline pragma.
870- inline := c .ctx .CreateEnumAttribute (llvm .AttributeKindID ("inlinehint" ), 0 )
871- frame .fn .LLVMFn .AddFunctionAttr (inline )
873+ inline := b .ctx .CreateEnumAttribute (llvm .AttributeKindID ("inlinehint" ), 0 )
874+ b .fn .LLVMFn .AddFunctionAttr (inline )
872875 case ir .InlineNone :
873876 // Add LLVM attribute to always avoid inlining this function.
874- noinline := c .ctx .CreateEnumAttribute (llvm .AttributeKindID ("noinline" ), 0 )
875- frame .fn .LLVMFn .AddFunctionAttr (noinline )
877+ noinline := b .ctx .CreateEnumAttribute (llvm .AttributeKindID ("noinline" ), 0 )
878+ b .fn .LLVMFn .AddFunctionAttr (noinline )
876879 }
877880
878881 // Add debug info, if needed.
879- if c .Debug () {
880- if frame .fn .Synthetic == "package initializer" {
882+ if b .Debug () {
883+ if b .fn .Synthetic == "package initializer" {
881884 // Package initializers have no debug info. Create some fake debug
882885 // info to at least have *something*.
883- frame .difunc = c .attachDebugInfoRaw (frame .fn , frame .fn .LLVMFn , "" , "" , 0 )
884- } else if frame .fn .Syntax () != nil {
886+ b .difunc = b .attachDebugInfoRaw (b .fn , b .fn .LLVMFn , "" , "" , 0 )
887+ } else if b .fn .Syntax () != nil {
885888 // Create debug info file if needed.
886- frame .difunc = c .attachDebugInfo (frame .fn )
889+ b .difunc = b .attachDebugInfo (b .fn )
887890 }
888- pos := c .ir .Program .Fset .Position (frame .fn .Pos ())
889- c . builder . SetCurrentDebugLocation (uint (pos .Line ), uint (pos .Column ), frame .difunc , llvm.Metadata {})
891+ pos := b .ir .Program .Fset .Position (b .fn .Pos ())
892+ b . SetCurrentDebugLocation (uint (pos .Line ), uint (pos .Column ), b .difunc , llvm.Metadata {})
890893 }
891894
892895 // Pre-create all basic blocks in the function.
893- for _ , block := range frame .fn .DomPreorder () {
894- llvmBlock := c .ctx .AddBasicBlock (frame .fn .LLVMFn , block .Comment )
895- frame .blockEntries [block ] = llvmBlock
896- frame .blockExits [block ] = llvmBlock
896+ for _ , block := range b .fn .DomPreorder () {
897+ llvmBlock := b .ctx .AddBasicBlock (b .fn .LLVMFn , block .Comment )
898+ b .blockEntries [block ] = llvmBlock
899+ b .blockExits [block ] = llvmBlock
897900 }
898- entryBlock := frame .blockEntries [frame .fn .Blocks [0 ]]
899- c . builder .SetInsertPointAtEnd (entryBlock )
901+ entryBlock := b .blockEntries [b .fn .Blocks [0 ]]
902+ b .SetInsertPointAtEnd (entryBlock )
900903
901904 // Load function parameters
902905 llvmParamIndex := 0
903- for _ , param := range frame .fn .Params {
904- llvmType := c .getLLVMType (param .Type ())
906+ for _ , param := range b .fn .Params {
907+ llvmType := b .getLLVMType (param .Type ())
905908 fields := make ([]llvm.Value , 0 , 1 )
906909 for range expandFormalParamType (llvmType ) {
907- fields = append (fields , frame .fn .LLVMFn .Param (llvmParamIndex ))
910+ fields = append (fields , b .fn .LLVMFn .Param (llvmParamIndex ))
908911 llvmParamIndex ++
909912 }
910- frame .locals [param ] = c .collapseFormalParam (llvmType , fields )
913+ b .locals [param ] = b .collapseFormalParam (llvmType , fields )
911914
912915 // Add debug information to this parameter (if available)
913- if c .Debug () && frame .fn .Syntax () != nil {
914- dbgParam := c .getLocalVariable (frame , param .Object ().(* types.Var ))
915- loc := c . builder .GetCurrentDebugLocation ()
916+ if b .Debug () && b .fn .Syntax () != nil {
917+ dbgParam := b .getLocalVariable (param .Object ().(* types.Var ))
918+ loc := b .GetCurrentDebugLocation ()
916919 if len (fields ) == 1 {
917- expr := c .dibuilder .CreateExpression (nil )
918- c .dibuilder .InsertValueAtEnd (fields [0 ], dbgParam , expr , loc , entryBlock )
920+ expr := b .dibuilder .CreateExpression (nil )
921+ b .dibuilder .InsertValueAtEnd (fields [0 ], dbgParam , expr , loc , entryBlock )
919922 } else {
920- fieldOffsets := c .expandFormalParamOffsets (llvmType )
923+ fieldOffsets := b .expandFormalParamOffsets (llvmType )
921924 for i , field := range fields {
922- expr := c .dibuilder .CreateExpression ([]int64 {
925+ expr := b .dibuilder .CreateExpression ([]int64 {
923926 0x1000 , // DW_OP_LLVM_fragment
924927 int64 (fieldOffsets [i ]) * 8 , // offset in bits
925- int64 (c .targetData .TypeAllocSize (field .Type ())) * 8 , // size in bits
928+ int64 (b .targetData .TypeAllocSize (field .Type ())) * 8 , // size in bits
926929 })
927- c .dibuilder .InsertValueAtEnd (field , dbgParam , expr , loc , entryBlock )
930+ b .dibuilder .InsertValueAtEnd (field , dbgParam , expr , loc , entryBlock )
928931 }
929932 }
930933 }
@@ -933,44 +936,44 @@ func (c *Compiler) parseFunc(frame *Frame) {
933936 // Load free variables from the context. This is a closure (or bound
934937 // method).
935938 var context llvm.Value
936- if ! frame .fn .IsExported () {
937- parentHandle := frame .fn .LLVMFn .LastParam ()
939+ if ! b .fn .IsExported () {
940+ parentHandle := b .fn .LLVMFn .LastParam ()
938941 parentHandle .SetName ("parentHandle" )
939942 context = llvm .PrevParam (parentHandle )
940943 context .SetName ("context" )
941944 }
942- if len (frame .fn .FreeVars ) != 0 {
945+ if len (b .fn .FreeVars ) != 0 {
943946 // Get a list of all variable types in the context.
944- freeVarTypes := make ([]llvm.Type , len (frame .fn .FreeVars ))
945- for i , freeVar := range frame .fn .FreeVars {
946- freeVarTypes [i ] = c .getLLVMType (freeVar .Type ())
947+ freeVarTypes := make ([]llvm.Type , len (b .fn .FreeVars ))
948+ for i , freeVar := range b .fn .FreeVars {
949+ freeVarTypes [i ] = b .getLLVMType (freeVar .Type ())
947950 }
948951
949952 // Load each free variable from the context pointer.
950953 // A free variable is always a pointer when this is a closure, but it
951954 // can be another type when it is a wrapper for a bound method (these
952955 // wrappers are generated by the ssa package).
953- for i , val := range c .emitPointerUnpack (context , freeVarTypes ) {
954- frame .locals [frame .fn .FreeVars [i ]] = val
956+ for i , val := range b .emitPointerUnpack (context , freeVarTypes ) {
957+ b .locals [b .fn .FreeVars [i ]] = val
955958 }
956959 }
957960
958- if frame .fn .Recover != nil {
961+ if b .fn .Recover != nil {
959962 // This function has deferred function calls. Set some things up for
960963 // them.
961- frame .deferInitFunc ()
964+ b .deferInitFunc ()
962965 }
963966
964967 // Fill blocks with instructions.
965- for _ , block := range frame .fn .DomPreorder () {
966- if c .DumpSSA () {
968+ for _ , block := range b .fn .DomPreorder () {
969+ if b .DumpSSA () {
967970 fmt .Printf ("%d: %s:\n " , block .Index , block .Comment )
968971 }
969- c . builder . SetInsertPointAtEnd (frame .blockEntries [block ])
970- frame .currentBlock = block
972+ b . SetInsertPointAtEnd (b .blockEntries [block ])
973+ b .currentBlock = block
971974 for _ , instr := range block .Instrs {
972975 if instr , ok := instr .(* ssa.DebugRef ); ok {
973- if ! c .Debug () {
976+ if ! b .Debug () {
974977 continue
975978 }
976979 object := instr .Object ()
@@ -984,35 +987,35 @@ func (c *Compiler) parseFunc(frame *Frame) {
984987 // for example.
985988 continue
986989 }
987- dbgVar := c .getLocalVariable (frame , variable )
988- pos := c .ir .Program .Fset .Position (instr .Pos ())
989- c .dibuilder .InsertValueAtEnd (frame .getValue (instr .X ), dbgVar , c .dibuilder .CreateExpression (nil ), llvm.DebugLoc {
990+ dbgVar := b .getLocalVariable (variable )
991+ pos := b .ir .Program .Fset .Position (instr .Pos ())
992+ b .dibuilder .InsertValueAtEnd (b .getValue (instr .X ), dbgVar , b .dibuilder .CreateExpression (nil ), llvm.DebugLoc {
990993 Line : uint (pos .Line ),
991994 Col : uint (pos .Column ),
992- Scope : frame .difunc ,
993- }, c . builder .GetInsertBlock ())
995+ Scope : b .difunc ,
996+ }, b .GetInsertBlock ())
994997 continue
995998 }
996- if c .DumpSSA () {
999+ if b .DumpSSA () {
9971000 if val , ok := instr .(ssa.Value ); ok && val .Name () != "" {
9981001 fmt .Printf ("\t %s = %s\n " , val .Name (), val .String ())
9991002 } else {
10001003 fmt .Printf ("\t %s\n " , instr .String ())
10011004 }
10021005 }
1003- frame .createInstruction (instr )
1006+ b .createInstruction (instr )
10041007 }
1005- if frame .fn .Name () == "init" && len (block .Instrs ) == 0 {
1006- c . builder .CreateRetVoid ()
1008+ if b .fn .Name () == "init" && len (block .Instrs ) == 0 {
1009+ b .CreateRetVoid ()
10071010 }
10081011 }
10091012
10101013 // Resolve phi nodes
1011- for _ , phi := range frame .phis {
1014+ for _ , phi := range b .phis {
10121015 block := phi .ssa .Block ()
10131016 for i , edge := range phi .ssa .Edges {
1014- llvmVal := frame .getValue (edge )
1015- llvmBlock := frame .blockExits [block.Preds [i ]]
1017+ llvmVal := b .getValue (edge )
1018+ llvmBlock := b .blockExits [block.Preds [i ]]
10161019 phi .llvm .AddIncoming ([]llvm.Value {llvmVal }, []llvm.BasicBlock {llvmBlock })
10171020 }
10181021 }
0 commit comments