// globalVarDecl lowers the given global variable declaration to LLVM IR, // emitting code to m. func (m *Module) globalVarDecl(n *ast.VarDecl) { // Input: // int x; // Output: // @x = global i32 0 ident := n.Name() dbg.Printf("create global variable: %v", n) typ := toIrType(n.Type()) var val value.Value switch { case n.Val != nil: panic("support for global variable initializer not yet implemented") case irtypes.IsInt(typ): var err error val, err = constant.NewInt(typ, "0") if err != nil { panic(fmt.Sprintf("unable to create integer constant; %v", err)) } default: val = constant.NewZeroInitializer(typ) } global, err := ir.NewGlobalDef(ident.Name, val, false) if err != nil { panic(fmt.Sprintf("unable to create global variable definition %q", ident)) } m.setIdentValue(ident, global) // Emit global variable definition. m.emitGlobal(global) }
// NewValue returns a new value based on the given type and value. func NewValue(typ, val interface{}) (value.Value, error) { // TODO: Verify type equality between typ and val.Type(). // * handled by constant.NewInt // * ... if typ, ok := typ.(types.Type); ok { switch val := val.(type) { case *LocalDummy: return val, nil case *Global: // TODO: Retreive type from val.typ once support for forward reference // of global variable declarations have been added. // TODO: Add type-check between ptrType and val.typ. if typ, ok := typ.(*types.Pointer); ok { return constant.NewPointer(typ, val.name) } return nil, errutil.Newf("invalid global type; expected *types.Pointer, got %T", typ) case *IntConst: return constant.NewInt(typ, val.val) case *NullPointerConst: if typ, ok := typ.(*types.Pointer); ok { return constant.NewNullPointer(typ) } return nil, errutil.Newf("invalid null pointer type; expected *types.Pointer, got %T", typ) case *CharArrayConst: return constant.NewCharArray(typ, val.val) case *ZeroInitializer: return constant.NewZeroInitializer(typ), nil case *GetElementPtrExpr: return constant.NewGetElementPtr(val.elem, val.addr, val.indices) default: pretty.Println(val) panic(fmt.Sprintf("support for value type %T not yet implemented", val)) } } return nil, errutil.Newf("invalid value type; expected types.Type, got %T", typ) }