예제 #1
0
            public Function(CodeGeneratorContext genContext, FunctionDefinitionNode leaf)
            {
                _leaf = leaf;

                // Create function type and add the function node without appending any basic blocks
                // This results in a function declaration in LLVM-IR
                Type[] paramTypes =
                    Array.ConvertAll(leaf.Parameters, param => genContext.LookupType(param.Type) !.Value);
                FunctionType =
                    genContext.Context.FunctionType(genContext.LookupType(leaf.ReturnType) !.Value, paramTypes, false);
                FunctionValue = genContext.Module.AddFunction(leaf.Name, FunctionType);

                // Process the static keyword in the same manner as clang
                FunctionValue.SetLinkage(leaf.IsExported
                    ? LLVMLinkage.LLVMExternalLinkage
                    : LLVMLinkage.LLVMInternalLinkage);

                genContext.TryGetNodeSymbol(leaf, out Symbol range);
                DiFwdDecl = genContext.DiBuilder.CreateReplaceableCompositeType(
                    LLVMDWARFTag.subroutine_type, leaf.Name, genContext.DiFile, genContext.DiFile,
                    range.LLVMLine, 0, 0, 0, LLVMDIFlags.LLVMDIFlagFwdDecl, "");
            }
예제 #2
0
            /// <summary>
            /// Add entry basic block to this function and fill in additional debug info.
            /// If not called, this is a function declaration.
            /// </summary>
            /// <param name="genContext"></param>
            /// <param name="builder"></param>
            /// <returns>Entry basic block</returns>
            public BasicBlock StartDefinition(CodeGeneratorContext genContext, Builder builder)
            {
                BasicBlock basicBlock = genContext.Context.AppendBasicBlock(FunctionValue, "entry");

                builder.PositionAtEnd(basicBlock);

                // Build return value storage if necessary
                Type returnType = FunctionType.ReturnType;

                if (returnType.Kind != LLVMTypeKind.LLVMVoidTypeKind)
                {
                    ReturnBlock   = genContext.Context.CreateBasicBlock("return");
                    RetvalStorage = builder.BuildAlloca(returnType, "retval");
                }

                // Visit all declaration nodes and create storage (parameters and variables)
                StackLayoutGenerator layoutGenerator = new StackLayoutGenerator(new IndexTypeSizeManager());

                layoutGenerator.VisitFunctionDefinition(_leaf);
                FunctionStackLayout layout = layoutGenerator.GetLayout();

                foreach (var v in layout.Variables)
                {
                    Type  varType    = genContext.LookupType(v.Key.Type) !.Value;
                    Value varStorage = builder.BuildAlloca(varType, v.Key.Name);
                    VariableValues[v.Key] = varStorage;
                }

                // Emit store instruction for return value
                if (RetvalStorage != null && !returnType.IsStructType())
                {
                    builder.BuildStore(Value.ConstInt(returnType, 0, true), RetvalStorage.Value);
                }

                // Emit store instructions for parameters
                Value[] funcParams = FunctionValue.Params;
                for (int i = 0, ilen = funcParams.Length; i < ilen; ++i)
                {
                    DeclarationNode parameter  = _leaf.Parameters[i];
                    Value           paramValue = funcParams[i];
                    VariableValues.TryGetValue(parameter, out Value varStorage);
                    varStorage.SetName($"{parameter.Name}.addr");
                    builder.BuildStore(paramValue, varStorage);
                    paramValue.SetName(parameter.Name);
                }

                // Create subroutine type debug info
                genContext.TryGetNodeSymbol(_leaf, out Symbol range);
                Metadata subroutineType = genContext.DiBuilder.CreateSubroutineType(genContext.DiFile,
                                                                                    Array.ConvertAll(_leaf.Parameters, param => genContext.LookupDiType(param.Type) !.Value),
                                                                                    LLVMDIFlags.LLVMDIFlagZero);
                Metadata funcLocation = genContext.Context.CreateDebugLocation(range.LLVMLine,
                                                                               genContext.ColumnInfo ? range.LLVMColumn : 0, DiFwdDecl, Metadata.Null);

                // Create subroutine debug info and substitute over forward declaration
                DiFunctionDef = genContext.DiBuilder.CreateFunction(genContext.DiFile, _leaf.Name, _leaf.Name,
                                                                    genContext.DiFile, range.LLVMLine, subroutineType, true, true, range.LLVMLine,
                                                                    LLVMDIFlags.LLVMDIFlagZero, false);
                DiFwdDecl.ReplaceAllUsesWith(DiFunctionDef);

                // Create llvm.dbg.declare calls for each parameter's storage
                if (genContext.DebugInfo)
                {
                    Metadata paramExpression = genContext.DiBuilder.CreateExpression();
                    for (int i = 0, ilen = _leaf.Parameters.Length; i < ilen; ++i)
                    {
                        DeclarationNode parameter = _leaf.Parameters[i];
                        genContext.TryGetNodeSymbol(parameter, out Symbol paramRange);
                        Metadata paramType     = genContext.LookupDiType(parameter.Type) !.Value;
                        Metadata paramMetadata = genContext.DiBuilder.CreateParameterVariable(DiFunctionDef,
                                                                                              parameter.Name, (uint)i + 1, genContext.DiFile, paramRange.LLVMLine, paramType, true,
                                                                                              LLVMDIFlags.LLVMDIFlagZero);
                        VariableValues.TryGetValue(parameter, out Value varStorage);
                        genContext.DiBuilder.InsertDeclareAtEnd(varStorage, paramMetadata, paramExpression,
                                                                funcLocation, basicBlock);
                    }
                }

                // Associate debug info nodes with function
                FunctionValue.SetFuncSubprogram(DiFunctionDef);

                return(basicBlock);
            }