Beispiel #1
0
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
}
Beispiel #2
0
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)
		}
	}
}