func (v *Codegen) genVariableDecl(n *parser.VariableDecl, semicolon bool) llvm.Value { var res llvm.Value if v.inFunction() { mangledName := n.Variable.MangledName(parser.MANGLE_ARK_UNSTABLE) funcEntry := v.currentLLVMFunction().EntryBasicBlock() // use this builder() for the variable alloca // this means all allocas go at the start of the function // so each variable is only allocated once allocBuilder := llvm.NewBuilder() if funcEntry == v.builder().GetInsertBlock() { allocBuilder.SetInsertPointAtEnd(funcEntry) } else { allocBuilder.SetInsertPointBefore(funcEntry.LastInstruction()) } varType := v.typeToLLVMType(n.Variable.Type) alloc := allocBuilder.CreateAlloca(varType, mangledName) allocBuilder.Dispose() v.variableLookup[n.Variable] = alloc if n.Assignment != nil { if value := v.genExpr(n.Assignment); !value.IsNil() { v.builder().CreateStore(value, alloc) } } } else { // TODO cbindings cBinding := false mangledName := n.Variable.MangledName(parser.MANGLE_ARK_UNSTABLE) varType := v.typeToLLVMType(n.Variable.Type) value := llvm.AddGlobal(v.curFile.LlvmModule, varType, mangledName) // TODO: External by default to export everything, change once we get access specifiers if !cBinding && !n.IsPublic() { value.SetLinkage(nonPublicLinkage) } value.SetGlobalConstant(!n.Variable.Mutable) if n.Assignment != nil { value.SetInitializer(v.genExpr(n.Assignment)) } v.variableLookup[n.Variable] = value } return res }
func (v *AttributeCheck) CheckVariableDecl(s *SemanticAnalyzer, n *parser.VariableDecl) { v.CheckAttrsDistanceFromLine(s, n.Variable.Attrs, n.Pos().Line, "variable", n.Variable.Name) for _, attr := range n.Variable.Attrs { switch attr.Key { case "deprecated": // value is optional, nothing to check case "unused": default: s.Err(attr, "Invalid variable attribute key `%s`", attr.Key) } } }