// NewAllocaInst returns a new allocation instruction based on the given element // type and number of elements. func NewAllocaInst(typ, nelems interface{}) (*instruction.Alloca, error) { if typ, ok := typ.(types.Type); ok { switch nelems := nelems.(type) { case *token.Token: n, err := strconv.Atoi(string(nelems.Lit)) if err != nil { return nil, errutil.Err(err) } return instruction.NewAlloca(typ, n) case int: return instruction.NewAlloca(typ, nelems) default: panic(fmt.Sprintf("support for number of elements type %T not yet implemented", nelems)) } } return nil, errutil.Newf("invalid element type; expected types.Type, got %T", typ) }
// localVarDef lowers the given local variable definition to LLVM IR, emitting // code to f. func (m *Module) localVarDef(f *Function, n *ast.VarDecl) { // Input: // void f() { // int a; // <-- relevant line // } // Output: // %a = alloca i32 ident := n.Name() dbg.Printf("create local variable: %v", n) typ := toIrType(n.Type()) allocaInst, err := instruction.NewAlloca(typ, 1) if err != nil { panic(fmt.Sprintf("unable to create alloca instruction; %v", err)) } // Emit local variable definition. f.emitLocal(ident, allocaInst) if n.Val != nil { panic("support for local variable definition initializer not yet implemented") } }
// funcParam lowers the given function parameter to LLVM IR, emitting code to f. func (m *Module) funcParam(f *Function, param *irtypes.Param) value.Value { // Input: // void f(int a) { // } // Output: // %1 = alloca i32 // store i32 %a, i32* %1 allocaInst, err := instruction.NewAlloca(param.Type(), 1) if err != nil { panic(fmt.Sprintf("unable to create alloca instruction; %v", err)) } // Emit local variable definition for the given function parameter. addr := f.emitInst(allocaInst) storeInst, err := instruction.NewStore(param, addr) if err != nil { panic(fmt.Sprintf("unable to create store instruction; %v", err)) } f.curBlock.AppendInst(storeInst) return addr }