Start defining a function so that it can be filled with instructions: load parameters, create basic blocks, and set up debug information. This is separated out from createFunction() so that it is also usable to define compiler intrinsics like the atomic operations in sync/atomic.
(intrinsic bool)
| 1154 | // This is separated out from createFunction() so that it is also usable to |
| 1155 | // define compiler intrinsics like the atomic operations in sync/atomic. |
| 1156 | func (b *builder) createFunctionStart(intrinsic bool) { |
| 1157 | if b.DumpSSA { |
| 1158 | fmt.Printf("\nfunc %s:\n", b.fn) |
| 1159 | } |
| 1160 | if !b.llvmFn.IsDeclaration() { |
| 1161 | errValue := b.llvmFn.Name() + " redeclared in this program" |
| 1162 | fnPos := getPosition(b.llvmFn) |
| 1163 | if fnPos.IsValid() { |
| 1164 | errValue += "\n\tprevious declaration at " + fnPos.String() |
| 1165 | } |
| 1166 | b.addError(b.fn.Pos(), errValue) |
| 1167 | return |
| 1168 | } |
| 1169 | |
| 1170 | b.addStandardDefinedAttributes(b.llvmFn) |
| 1171 | if !b.info.exported { |
| 1172 | // Do not set visibility for local linkage (internal or private). |
| 1173 | // Otherwise a "local linkage requires default visibility" |
| 1174 | // assertion error in llvm-project/llvm/include/llvm/IR/GlobalValue.h:236 |
| 1175 | // is thrown. |
| 1176 | if b.llvmFn.Linkage() != llvm.InternalLinkage && |
| 1177 | b.llvmFn.Linkage() != llvm.PrivateLinkage { |
| 1178 | b.llvmFn.SetVisibility(llvm.HiddenVisibility) |
| 1179 | } |
| 1180 | b.llvmFn.SetUnnamedAddr(true) |
| 1181 | } |
| 1182 | if b.info.section != "" { |
| 1183 | b.llvmFn.SetSection(b.info.section) |
| 1184 | } |
| 1185 | if b.info.exported && strings.HasPrefix(b.Triple, "wasm") { |
| 1186 | // Set the exported name. This is necessary for WebAssembly because |
| 1187 | // otherwise the function is not exported. |
| 1188 | functionAttr := b.ctx.CreateStringAttribute("wasm-export-name", b.info.linkName) |
| 1189 | b.llvmFn.AddFunctionAttr(functionAttr) |
| 1190 | // Unlike most targets, exported functions are actually visible in |
| 1191 | // WebAssembly (even if it's not called from within the WebAssembly |
| 1192 | // module). But LTO generally optimizes such functions away. Therefore, |
| 1193 | // exported functions must be explicitly marked as used. |
| 1194 | llvmutil.AppendToGlobal(b.mod, "llvm.used", b.llvmFn) |
| 1195 | } |
| 1196 | |
| 1197 | // Some functions have a pragma controlling the inlining level. |
| 1198 | switch b.info.inline { |
| 1199 | case inlineHint: |
| 1200 | // Add LLVM inline hint to functions with //go:inline pragma. |
| 1201 | inline := b.ctx.CreateEnumAttribute(llvm.AttributeKindID("inlinehint"), 0) |
| 1202 | b.llvmFn.AddFunctionAttr(inline) |
| 1203 | case inlineNone: |
| 1204 | // Add LLVM attribute to always avoid inlining this function. |
| 1205 | noinline := b.ctx.CreateEnumAttribute(llvm.AttributeKindID("noinline"), 0) |
| 1206 | b.llvmFn.AddFunctionAttr(noinline) |
| 1207 | } |
| 1208 | |
| 1209 | if b.info.interrupt { |
| 1210 | // Mark this function as an interrupt. |
| 1211 | // This is necessary on MCUs that don't push caller saved registers when |
| 1212 | // entering an interrupt, such as on AVR. |
| 1213 | if strings.HasPrefix(b.Triple, "avr") { |
no test coverage detected