本文整理匯總了Golang中github.com/axw/gollvm/llvm.SizeOf函數的典型用法代碼示例。如果您正苦於以下問題:Golang SizeOf函數的具體用法?Golang SizeOf怎麽用?Golang SizeOf使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。
在下文中一共展示了SizeOf函數的13個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: makeSlice
// makeSlice allocates a new slice with the optional length and capacity,
// initialising its contents to their zero values.
func (c *compiler) makeSlice(elttyp types.Type, length, capacity Value) llvm.Value {
var lengthValue llvm.Value
if length != nil {
lengthValue = length.Convert(types.Typ[types.Int]).LLVMValue()
} else {
lengthValue = llvm.ConstNull(c.llvmtypes.inttype)
}
// TODO check capacity >= length
capacityValue := lengthValue
if capacity != nil {
capacityValue = capacity.Convert(types.Typ[types.Int]).LLVMValue()
}
eltType := c.types.ToLLVM(elttyp)
sizeof := llvm.ConstTruncOrBitCast(llvm.SizeOf(eltType), c.types.inttype)
size := c.builder.CreateMul(capacityValue, sizeof, "")
mem := c.createMalloc(size)
mem = c.builder.CreateIntToPtr(mem, llvm.PointerType(eltType, 0), "")
c.memsetZero(mem, size)
slicetyp := types.NewSlice(elttyp)
struct_ := llvm.Undef(c.types.ToLLVM(slicetyp))
struct_ = c.builder.CreateInsertValue(struct_, mem, 0, "")
struct_ = c.builder.CreateInsertValue(struct_, lengthValue, 1, "")
struct_ = c.builder.CreateInsertValue(struct_, capacityValue, 2, "")
return struct_
}
示例2: makeSlice
// makeSlice allocates a new slice with the optional length and capacity,
// initialising its contents to their zero values.
func (c *compiler) makeSlice(elttyp types.Type, length, capacity Value) llvm.Value {
var lengthValue llvm.Value
if length != nil {
lengthValue = length.Convert(types.Int32).LLVMValue()
} else {
lengthValue = llvm.ConstNull(llvm.Int32Type())
}
// TODO check capacity >= length
capacityValue := lengthValue
if capacity != nil {
capacityValue = capacity.Convert(types.Int32).LLVMValue()
}
llvmelttyp := c.types.ToLLVM(elttyp)
mem := c.builder.CreateArrayMalloc(llvmelttyp, capacityValue, "")
sizeof := llvm.ConstTrunc(llvm.SizeOf(llvmelttyp), llvm.Int32Type())
size := c.builder.CreateMul(capacityValue, sizeof, "")
c.memsetZero(mem, size)
slicetyp := types.Slice{Elt: elttyp}
struct_ := llvm.Undef(c.types.ToLLVM(&slicetyp))
struct_ = c.builder.CreateInsertValue(struct_, mem, 0, "")
struct_ = c.builder.CreateInsertValue(struct_, lengthValue, 1, "")
struct_ = c.builder.CreateInsertValue(struct_, capacityValue, 2, "")
return struct_
}
示例3: VisitLen
func (c *compiler) VisitLen(expr *ast.CallExpr) Value {
if len(expr.Args) > 1 {
panic("Expecting only one argument to len")
}
value := c.VisitExpr(expr.Args[0])
typ := value.Type()
if name, ok := typ.(*types.Name); ok {
typ = name.Underlying
}
switch typ := typ.(type) {
case *types.Pointer:
// XXX Converting to a string to be converted back to an int is
// silly. The values need an overhaul? Perhaps have types based
// on fundamental types, with the additional methods to make
// them llgo.Value's.
if a, isarray := typ.Base.(*types.Array); isarray {
return c.NewConstValue(token.INT,
strconv.FormatUint(a.Len, 10))
}
v := strconv.FormatUint(uint64(unsafe.Sizeof(uintptr(0))), 10)
return c.NewConstValue(token.INT, v)
case *types.Slice:
ptr := value.(*LLVMValue).pointer
len_field := c.builder.CreateStructGEP(ptr.LLVMValue(), 1, "")
len_value := c.builder.CreateLoad(len_field, "")
return c.NewLLVMValue(len_value, types.Int32).Convert(types.Int)
case *types.Array:
v := strconv.FormatUint(typ.Len, 10)
return c.NewConstValue(token.INT, v)
case *types.Struct:
sz := llvm.SizeOf(c.types.ToLLVM(typ))
// FIXME
// SizeOf returns a Constant, but not a ConstantInt, so we
// can't call ZExtValue on it. Not sure how best to tackle
// this, so for now returning this as a non-const value.
//return c.NewConstValue(token.INT, string(sz.ZExtValue()))
return c.NewLLVMValue(sz, types.Int)
case *types.Basic:
if typ == types.String.Underlying {
ptr := value.(*LLVMValue).pointer
len_field := c.builder.CreateStructGEP(ptr.LLVMValue(), 1, "")
len_value := c.builder.CreateLoad(len_field, "")
return c.NewLLVMValue(len_value, types.Int32).Convert(types.Int)
}
}
panic(fmt.Sprint("Unhandled value type: ", value.Type()))
}
示例4: makeLiteralSlice
// makeLiteralSlice allocates a new slice, storing in it the provided elements.
func (c *compiler) makeLiteralSlice(v []llvm.Value, elttyp types.Type) llvm.Value {
n := llvm.ConstInt(c.types.inttype, uint64(len(v)), false)
eltType := c.types.ToLLVM(elttyp)
arrayType := llvm.ArrayType(eltType, len(v))
mem := c.createMalloc(llvm.SizeOf(arrayType))
mem = c.builder.CreateIntToPtr(mem, llvm.PointerType(eltType, 0), "")
for i, value := range v {
indices := []llvm.Value{llvm.ConstInt(llvm.Int32Type(), uint64(i), false)}
ep := c.builder.CreateGEP(mem, indices, "")
c.builder.CreateStore(value, ep)
}
slicetyp := types.NewSlice(elttyp)
struct_ := llvm.Undef(c.types.ToLLVM(slicetyp))
struct_ = c.builder.CreateInsertValue(struct_, mem, 0, "")
struct_ = c.builder.CreateInsertValue(struct_, n, 1, "")
struct_ = c.builder.CreateInsertValue(struct_, n, 2, "")
return struct_
}
示例5: makeRtype
func (tm *TypeMap) makeRtype(t types.Type, k reflect.Kind) llvm.Value {
// Not sure if there's an easier way to do this, but if you just
// use ConstStruct, you end up getting a different llvm.Type.
lt := tm.ToLLVM(t)
typ := llvm.ConstNull(tm.runtimeType)
elementTypes := tm.runtimeType.StructElementTypes()
// Size.
size := llvm.SizeOf(lt)
if size.Type().IntTypeWidth() > elementTypes[0].IntTypeWidth() {
size = llvm.ConstTrunc(size, elementTypes[0])
}
typ = llvm.ConstInsertValue(typ, size, []uint32{0})
// TODO hash
// TODO padding
// Alignment.
align := llvm.ConstTrunc(llvm.AlignOf(lt), llvm.Int8Type())
typ = llvm.ConstInsertValue(typ, align, []uint32{3}) // var
typ = llvm.ConstInsertValue(typ, align, []uint32{4}) // field
// Kind.
kind := llvm.ConstInt(llvm.Int8Type(), uint64(k), false)
typ = llvm.ConstInsertValue(typ, kind, []uint32{5})
// Algorithm table.
alg := tm.makeAlgorithmTable(t)
algptr := llvm.AddGlobal(tm.module, alg.Type(), "")
algptr.SetInitializer(alg)
algptr = llvm.ConstBitCast(algptr, elementTypes[6])
typ = llvm.ConstInsertValue(typ, algptr, []uint32{6})
// String representation.
stringrep := tm.globalStringPtr(tm.TypeString(t))
typ = llvm.ConstInsertValue(typ, stringrep, []uint32{8})
// TODO gc
return typ
}
示例6: instruction
func (fr *frame) instruction(instr ssa.Instruction) {
fr.logf("[%T] %v @ %s\n", instr, instr, fr.pkg.Prog.Fset.Position(instr.Pos()))
// Check if we'll need to backpatch; see comment
// in fr.value().
if v, ok := instr.(ssa.Value); ok {
if b := fr.backpatcher(v); b != nil {
defer b()
}
}
switch instr := instr.(type) {
case *ssa.Alloc:
typ := fr.llvmtypes.ToLLVM(deref(instr.Type()))
var value llvm.Value
if instr.Heap {
value = fr.createTypeMalloc(typ)
value.SetName(instr.Comment)
fr.env[instr] = fr.NewValue(value, instr.Type())
} else {
value = fr.env[instr].LLVMValue()
}
fr.memsetZero(value, llvm.SizeOf(typ))
case *ssa.BinOp:
lhs, rhs := fr.value(instr.X), fr.value(instr.Y)
fr.env[instr] = lhs.BinaryOp(instr.Op, rhs).(*LLVMValue)
case *ssa.Call:
fn, args, result := fr.prepareCall(instr)
// Some builtins may only be used immediately, and not
// deferred; in this case, "fn" will be nil, and result
// may be non-nil (it will be nil for builtins without
// results.)
if fn == nil {
if result != nil {
fr.env[instr] = result
}
} else {
result = fr.createCall(fn, args)
fr.env[instr] = result
}
case *ssa.ChangeInterface:
x := fr.value(instr.X)
// The source type must be a non-empty interface,
// as ChangeInterface cannot fail (E2I may fail).
if instr.Type().Underlying().(*types.Interface).NumMethods() > 0 {
// TODO(axw) optimisation for I2I case where we
// know statically the methods to carry over.
x = x.convertI2E()
x, _ = x.convertE2I(instr.Type())
} else {
x = x.convertI2E()
x = fr.NewValue(x.LLVMValue(), instr.Type())
}
fr.env[instr] = x
case *ssa.ChangeType:
value := fr.value(instr.X).LLVMValue()
if _, ok := instr.Type().Underlying().(*types.Pointer); ok {
value = fr.builder.CreateBitCast(value, fr.llvmtypes.ToLLVM(instr.Type()), "")
}
v := fr.NewValue(value, instr.Type())
if _, ok := instr.X.(*ssa.Phi); ok {
v = phiValue(fr.compiler, v)
}
fr.env[instr] = v
case *ssa.Convert:
v := fr.value(instr.X)
if _, ok := instr.X.(*ssa.Phi); ok {
v = phiValue(fr.compiler, v)
}
fr.env[instr] = v.Convert(instr.Type()).(*LLVMValue)
//case *ssa.DebugRef:
case *ssa.Defer:
fn, args, result := fr.prepareCall(instr)
if result != nil {
panic("illegal use of builtin in defer statement")
}
fn = fr.indirectFunction(fn, args)
fr.createCall(fr.runtime.pushdefer, []*LLVMValue{fn})
case *ssa.Extract:
tuple := fr.value(instr.Tuple).LLVMValue()
elem := fr.builder.CreateExtractValue(tuple, instr.Index, instr.Name())
elemtyp := instr.Type()
fr.env[instr] = fr.NewValue(elem, elemtyp)
case *ssa.Field:
value := fr.value(instr.X).LLVMValue()
field := fr.builder.CreateExtractValue(value, instr.Field, instr.Name())
fieldtyp := instr.Type()
fr.env[instr] = fr.NewValue(field, fieldtyp)
case *ssa.FieldAddr:
// TODO: implement nil check and panic.
//.........這裏部分代碼省略.........
示例7: defineFunction
func (u *unit) defineFunction(f *ssa.Function) {
// Nothing to do for functions without bodies.
if len(f.Blocks) == 0 {
return
}
// Only define functions from this package.
if f.Pkg == nil {
if r := f.Signature.Recv(); r != nil && r.Pkg() != nil && r.Pkg() != u.pkg.Object {
return
}
} else if f.Pkg != u.pkg {
return
}
fr := frame{
unit: u,
blocks: make([]llvm.BasicBlock, len(f.Blocks)),
env: make(map[ssa.Value]*LLVMValue),
}
fr.logf("Define function: %s", f.String())
llvmFunction := fr.resolveFunction(f).LLVMValue()
delete(u.undefinedFuncs, f)
// Functions that call recover must not be inlined, or we
// can't tell whether the recover call is valid at runtime.
if f.Recover != nil {
llvmFunction.AddFunctionAttr(llvm.NoInlineAttribute)
}
for i, block := range f.Blocks {
fr.blocks[i] = llvm.AddBasicBlock(llvmFunction, fmt.Sprintf(".%d.%s", i, block.Comment))
}
fr.builder.SetInsertPointAtEnd(fr.blocks[0])
var paramOffset int
if len(f.FreeVars) > 0 {
// Extract captures from the first implicit parameter.
arg0 := llvmFunction.Param(0)
for i, fv := range f.FreeVars {
addressPtr := fr.builder.CreateStructGEP(arg0, i, "")
address := fr.builder.CreateLoad(addressPtr, "")
fr.env[fv] = fr.NewValue(address, fv.Type())
}
paramOffset++
}
for i, param := range f.Params {
fr.env[param] = fr.NewValue(llvmFunction.Param(i+paramOffset), param.Type())
}
// Allocate stack space for locals in the prologue block.
prologueBlock := llvm.InsertBasicBlock(fr.blocks[0], "prologue")
fr.builder.SetInsertPointAtEnd(prologueBlock)
for _, local := range f.Locals {
typ := fr.llvmtypes.ToLLVM(deref(local.Type()))
alloca := fr.builder.CreateAlloca(typ, local.Comment)
u.memsetZero(alloca, llvm.SizeOf(typ))
value := fr.NewValue(alloca, local.Type())
fr.env[local] = value
}
// Move any allocs relating to named results from the entry block
// to the prologue block, so they dominate the rundefers and recover
// blocks.
//
// TODO(axw) ask adonovan for a cleaner way of doing this, e.g.
// have ssa generate an entry block that defines Allocs and related
// stores, and then a separate block for function body instructions.
if f.Synthetic == "" {
if results := f.Signature.Results(); results != nil {
for i := 0; i < results.Len(); i++ {
result := results.At(i)
if result.Name() == "" {
break
}
for i, instr := range f.Blocks[0].Instrs {
if instr, ok := instr.(*ssa.Alloc); ok && instr.Heap && instr.Pos() == result.Pos() {
fr.instruction(instr)
instrs := f.Blocks[0].Instrs
instrs = append(instrs[:i], instrs[i+1:]...)
f.Blocks[0].Instrs = instrs
break
}
}
}
}
}
// If the function contains any defers, we must first call
// setjmp so we can call rundefers in response to a panic.
// We can short-circuit the check for defers with
// f.Recover != nil.
if f.Recover != nil || hasDefer(f) {
rdblock := llvm.AddBasicBlock(llvmFunction, "rundefers")
defers := fr.builder.CreateAlloca(fr.runtime.defers.llvm, "")
fr.builder.CreateCall(fr.runtime.initdefers.LLVMValue(), []llvm.Value{defers}, "")
jb := fr.builder.CreateStructGEP(defers, 0, "")
jb = fr.builder.CreateBitCast(jb, llvm.PointerType(llvm.Int8Type(), 0), "")
result := fr.builder.CreateCall(fr.runtime.setjmp.LLVMValue(), []llvm.Value{jb}, "")
//.........這裏部分代碼省略.........
示例8: VisitGoStmt
func (c *compiler) VisitGoStmt(stmt *ast.GoStmt) {
//stmt.Call *ast.CallExpr
// TODO
var fn *LLVMValue
switch x := (stmt.Call.Fun).(type) {
case *ast.Ident:
fn = c.Resolve(x.Obj).(*LLVMValue)
if fn == nil {
panic(fmt.Sprintf(
"No function found with name '%s'", x.String()))
}
default:
fn = c.VisitExpr(stmt.Call.Fun).(*LLVMValue)
}
// Evaluate arguments, store in a structure on the stack.
var args_struct_type llvm.Type
var args_mem llvm.Value
var args_size llvm.Value
if stmt.Call.Args != nil {
param_types := make([]llvm.Type, 0)
fn_type := types.Deref(fn.Type()).(*types.Func)
for _, param := range fn_type.Params {
typ := param.Type.(types.Type)
param_types = append(param_types, c.types.ToLLVM(typ))
}
args_struct_type = llvm.StructType(param_types, false)
args_mem = c.builder.CreateAlloca(args_struct_type, "")
for i, expr := range stmt.Call.Args {
value_i := c.VisitExpr(expr)
value_i = value_i.Convert(fn_type.Params[i].Type.(types.Type))
arg_i := c.builder.CreateGEP(args_mem, []llvm.Value{
llvm.ConstInt(llvm.Int32Type(), 0, false),
llvm.ConstInt(llvm.Int32Type(), uint64(i), false)}, "")
c.builder.CreateStore(value_i.LLVMValue(), arg_i)
}
args_size = llvm.SizeOf(args_struct_type)
args_size = llvm.ConstTrunc(args_size, llvm.Int32Type())
} else {
args_struct_type = llvm.VoidType()
args_mem = llvm.ConstNull(llvm.PointerType(args_struct_type, 0))
args_size = llvm.ConstInt(llvm.Int32Type(), 0, false)
}
// When done, return to where we were.
defer c.builder.SetInsertPointAtEnd(c.builder.GetInsertBlock())
// Create a function that will take a pointer to a structure of the type
// defined above, or no parameters if there are none to pass.
indirect_fn_type := llvm.FunctionType(
llvm.VoidType(),
[]llvm.Type{llvm.PointerType(args_struct_type, 0)}, false)
indirect_fn := llvm.AddFunction(c.module.Module, "", indirect_fn_type)
indirect_fn.SetFunctionCallConv(llvm.CCallConv)
// Call "newgoroutine" with the indirect function and stored args.
newgoroutine := getnewgoroutine(c.module.Module)
ngr_param_types := newgoroutine.Type().ElementType().ParamTypes()
fn_arg := c.builder.CreateBitCast(indirect_fn, ngr_param_types[0], "")
args_arg := c.builder.CreateBitCast(args_mem,
llvm.PointerType(llvm.Int8Type(), 0), "")
c.builder.CreateCall(newgoroutine,
[]llvm.Value{fn_arg, args_arg, args_size}, "")
entry := llvm.AddBasicBlock(indirect_fn, "entry")
c.builder.SetInsertPointAtEnd(entry)
var args []llvm.Value
if stmt.Call.Args != nil {
args_mem = indirect_fn.Param(0)
args = make([]llvm.Value, len(stmt.Call.Args))
for i := range stmt.Call.Args {
arg_i := c.builder.CreateGEP(args_mem, []llvm.Value{
llvm.ConstInt(llvm.Int32Type(), 0, false),
llvm.ConstInt(llvm.Int32Type(), uint64(i), false)}, "")
args[i] = c.builder.CreateLoad(arg_i, "")
}
}
c.builder.CreateCall(fn.LLVMValue(), args, "")
c.builder.CreateRetVoid()
}
示例9: chanSelect
func (c *compiler) chanSelect(states []selectState, blocking bool) *LLVMValue {
stackptr := c.stacksave()
defer c.stackrestore(stackptr)
n := uint64(len(states))
if !blocking {
// blocking means there's no default case
n++
}
lln := llvm.ConstInt(llvm.Int32Type(), n, false)
allocsize := c.builder.CreateCall(c.runtime.selectsize.LLVMValue(), []llvm.Value{lln}, "")
selectp := c.builder.CreateArrayAlloca(llvm.Int8Type(), allocsize, "selectp")
c.memsetZero(selectp, allocsize)
selectp = c.builder.CreatePtrToInt(selectp, c.target.IntPtrType(), "")
c.builder.CreateCall(c.runtime.selectinit.LLVMValue(), []llvm.Value{lln, selectp}, "")
// Allocate stack for the values to send/receive.
//
// TODO(axw) request optimisation in ssa to special-
// case receive cases with no assignment, so we know
// not to allocate stack space or do a copy.
resTypes := []types.Type{types.Typ[types.Int], types.Typ[types.Bool]}
for _, state := range states {
if state.Dir == types.RecvOnly {
chantyp := state.Chan.Type().Underlying().(*types.Chan)
resTypes = append(resTypes, chantyp.Elem())
}
}
resType := tupleType(resTypes...)
llResType := c.types.ToLLVM(resType)
tupleptr := c.builder.CreateAlloca(llResType, "")
c.memsetZero(tupleptr, llvm.SizeOf(llResType))
var recvindex int
ptrs := make([]llvm.Value, len(states))
for i, state := range states {
chantyp := state.Chan.Type().Underlying().(*types.Chan)
elemtyp := c.types.ToLLVM(chantyp.Elem())
if state.Dir == types.SendOnly {
ptrs[i] = c.builder.CreateAlloca(elemtyp, "")
c.builder.CreateStore(state.Send.LLVMValue(), ptrs[i])
} else {
ptrs[i] = c.builder.CreateStructGEP(tupleptr, recvindex+2, "")
recvindex++
}
ptrs[i] = c.builder.CreatePtrToInt(ptrs[i], c.target.IntPtrType(), "")
}
// Create select{send,recv} calls.
selectsend := c.runtime.selectsend.LLVMValue()
selectrecv := c.runtime.selectrecv.LLVMValue()
var received llvm.Value
if recvindex > 0 {
received = c.builder.CreateStructGEP(tupleptr, 1, "")
}
if !blocking {
c.builder.CreateCall(c.runtime.selectdefault.LLVMValue(), []llvm.Value{selectp}, "")
}
for i, state := range states {
ch := state.Chan.LLVMValue()
if state.Dir == types.SendOnly {
c.builder.CreateCall(selectsend, []llvm.Value{selectp, ch, ptrs[i]}, "")
} else {
c.builder.CreateCall(selectrecv, []llvm.Value{selectp, ch, ptrs[i], received}, "")
}
}
// Fire off the select.
index := c.builder.CreateCall(c.runtime.selectgo.LLVMValue(), []llvm.Value{selectp}, "")
tuple := c.builder.CreateLoad(tupleptr, "")
tuple = c.builder.CreateInsertValue(tuple, index, 0, "")
return c.NewValue(tuple, resType)
}
示例10: createTypeMalloc
func (c *compiler) createTypeMalloc(t llvm.Type) llvm.Value {
ptr := c.createMalloc(llvm.SizeOf(t))
return c.builder.CreateIntToPtr(ptr, llvm.PointerType(t, 0), "")
}
示例11: VisitValueSpec
func (c *compiler) VisitValueSpec(valspec *ast.ValueSpec, isconst bool) {
// Check if the value-spec has already been visited (referenced
// before definition visited.)
if len(valspec.Names) > 0 {
if _, ok := valspec.Names[0].Obj.Data.(Value); ok {
return
}
}
// Constants are evaluated during typechecking. We can just pull
// out the value from the name's object data.
if isconst {
for _, name := range valspec.Names {
if name.Name != "_" && name.Obj != nil {
value := name.Obj.Data.(types.Const)
typ := name.Obj.Type.(types.Type)
name.Obj.Data = ConstValue{value, c, typ}
}
}
return
}
pkgname, ispackagelevel := c.pkgmap[valspec.Names[0].Obj]
if ispackagelevel {
c.createGlobals(valspec.Names, valspec.Values, pkgname)
return
}
var values []Value
if len(valspec.Values) == 1 && len(valspec.Names) > 1 {
values = c.destructureExpr(valspec.Values[0])
} else if len(valspec.Values) > 0 {
values = make([]Value, len(valspec.Names))
for i := range valspec.Names {
values[i] = c.VisitExpr(valspec.Values[i])
}
}
for i, name := range valspec.Names {
if name.Name == "_" {
continue
}
// The variable should be allocated on the stack if it's
// declared inside a function.
//
// FIXME currently allocating all variables on the heap.
// Change this to allocate on the stack, and perform
// escape analysis to determine whether to promote.
typ := name.Obj.Type.(types.Type)
llvmtyp := c.types.ToLLVM(typ)
ptr := c.createTypeMalloc(llvmtyp)
if values == nil || values[i] == nil {
// If no initialiser was specified, bzero it.
bzero := c.NamedFunction("runtime.bzero", "func f(unsafe.Pointer, uintptr)")
ptr := c.builder.CreatePtrToInt(ptr, c.target.IntPtrType(), "")
args := []llvm.Value{ptr, llvm.SizeOf(llvmtyp)}
c.builder.CreateCall(bzero, args, "")
} else {
// FIXME we need to revisit how aggregate types
// are initialised/copied/etc. A CreateStore will
// try to do everything in registers, which is
// going to hurt when the aggregate is large.
llvmInit := values[i].Convert(typ).LLVMValue()
c.builder.CreateStore(llvmInit, ptr)
}
stackvar := c.NewLLVMValue(ptr, &types.Pointer{Base: typ}).makePointee()
stackvar.stack = c.functions[len(c.functions)-1]
name.Obj.Data = stackvar
}
}
示例12: VisitCompositeLit
func (c *compiler) VisitCompositeLit(lit *ast.CompositeLit) Value {
typ := c.types.expr[lit]
var valuemap map[interface{}]Value
var valuelist []Value
_, isstruct := types.Underlying(typ).(*types.Struct)
if lit.Elts != nil {
for _, elt := range lit.Elts {
var value Value
if kv, iskv := elt.(*ast.KeyValueExpr); iskv {
value = c.VisitExpr(kv.Value)
if valuemap == nil {
valuemap = make(map[interface{}]Value)
}
var key interface{}
if isstruct {
key = kv.Key.(*ast.Ident).Name
} else {
key = c.VisitExpr(kv.Key)
}
valuemap[key] = value
} else {
value = c.VisitExpr(elt)
valuelist = append(valuelist, value)
}
}
}
// For array/slice types, convert key:value to contiguous
// values initialiser.
switch types.Underlying(typ).(type) {
case *types.Array, *types.Slice:
if len(valuemap) > 0 {
maxi := int64(-1)
for key, _ := range valuemap {
i := key.(ConstValue).Int64()
if i < 0 {
panic("array index must be non-negative integer constant")
} else if i > maxi {
maxi = i
}
}
valuelist = make([]Value, maxi+1)
for key, value := range valuemap {
i := key.(ConstValue).Int64()
valuelist[i] = value
}
}
}
origtyp := typ
switch typ := types.Underlying(typ).(type) {
case *types.Array:
elttype := typ.Elt
llvmelttype := c.types.ToLLVM(elttype)
llvmvalues := make([]llvm.Value, typ.Len)
for i := range llvmvalues {
var value Value
if i < len(valuelist) {
value = valuelist[i]
}
if value == nil {
llvmvalues[i] = llvm.ConstNull(llvmelttype)
} else if _, ok := value.(ConstValue); ok || value.LLVMValue().IsConstant() {
llvmvalues[i] = value.Convert(elttype).LLVMValue()
} else {
llvmvalues[i] = llvm.Undef(llvmelttype)
}
}
array := llvm.ConstArray(llvmelttype, llvmvalues)
for i, value := range valuelist {
if llvmvalues[i].IsUndef() {
value := value.Convert(elttype).LLVMValue()
array = c.builder.CreateInsertValue(array, value, i, "")
}
}
return c.NewLLVMValue(array, origtyp)
case *types.Slice:
ptr := c.createTypeMalloc(c.types.ToLLVM(typ))
eltType := c.types.ToLLVM(typ.Elt)
arrayType := llvm.ArrayType(eltType, len(valuelist))
valuesPtr := c.createMalloc(llvm.SizeOf(arrayType))
valuesPtr = c.builder.CreateIntToPtr(valuesPtr, llvm.PointerType(eltType, 0), "")
//valuesPtr = c.builder.CreateBitCast(valuesPtr, llvm.PointerType(valuesPtr.Type(), 0), "")
// TODO check result of mallocs
length := llvm.ConstInt(llvm.Int32Type(), uint64(len(valuelist)), false)
c.builder.CreateStore(valuesPtr, c.builder.CreateStructGEP(ptr, 0, "")) // data
c.builder.CreateStore(length, c.builder.CreateStructGEP(ptr, 1, "")) // len
c.builder.CreateStore(length, c.builder.CreateStructGEP(ptr, 2, "")) // cap
null := llvm.ConstNull(c.types.ToLLVM(typ.Elt))
for i, value := range valuelist {
index := llvm.ConstInt(llvm.Int32Type(), uint64(i), false)
valuePtr := c.builder.CreateGEP(valuesPtr, []llvm.Value{index}, "")
if value == nil {
c.builder.CreateStore(null, valuePtr)
} else {
c.builder.CreateStore(value.Convert(typ.Elt).LLVMValue(), valuePtr)
}
//.........這裏部分代碼省略.........
示例13: VisitCompositeLit
//.........這裏部分代碼省略.........
for key, _ := range valuemap {
key, _ := exact.Uint64Val(key.(exact.Value))
if key > maxkey {
maxkey = key
}
}
valuelist = make([]Value, maxkey+1)
for key, value := range valuemap {
key, _ := exact.Uint64Val(key.(exact.Value))
valuelist[key] = value
}
}
}
origtyp := typ
switch typ := typ.Underlying().(type) {
case *types.Array:
elttype := typ.Elem()
llvmelttype := c.types.ToLLVM(elttype)
llvmvalues := make([]llvm.Value, typ.Len())
for i := range llvmvalues {
var value Value
if i < len(valuelist) {
value = valuelist[i]
}
if value == nil {
llvmvalues[i] = llvm.ConstNull(llvmelttype)
} else if value.LLVMValue().IsConstant() {
llvmvalues[i] = value.Convert(elttype).LLVMValue()
} else {
llvmvalues[i] = llvm.Undef(llvmelttype)
}
}
array := llvm.ConstArray(llvmelttype, llvmvalues)
for i, value := range valuelist {
if llvmvalues[i].IsUndef() {
value := value.Convert(elttype).LLVMValue()
array = c.builder.CreateInsertValue(array, value, i, "")
}
}
return c.NewValue(array, origtyp)
case *types.Slice:
ptr := c.createTypeMalloc(c.types.ToLLVM(typ))
eltType := c.types.ToLLVM(typ.Elem())
arrayType := llvm.ArrayType(eltType, len(valuelist))
valuesPtr := c.createMalloc(llvm.SizeOf(arrayType))
valuesPtr = c.builder.CreateIntToPtr(valuesPtr, llvm.PointerType(eltType, 0), "")
//valuesPtr = c.builder.CreateBitCast(valuesPtr, llvm.PointerType(valuesPtr.Type(), 0), "")
length := llvm.ConstInt(c.types.inttype, uint64(len(valuelist)), false)
c.builder.CreateStore(valuesPtr, c.builder.CreateStructGEP(ptr, 0, "")) // data
c.builder.CreateStore(length, c.builder.CreateStructGEP(ptr, 1, "")) // len
c.builder.CreateStore(length, c.builder.CreateStructGEP(ptr, 2, "")) // cap
null := llvm.ConstNull(c.types.ToLLVM(typ.Elem()))
for i, value := range valuelist {
index := llvm.ConstInt(llvm.Int32Type(), uint64(i), false)
valuePtr := c.builder.CreateGEP(valuesPtr, []llvm.Value{index}, "")
if value == nil {
c.builder.CreateStore(null, valuePtr)
} else {
c.builder.CreateStore(value.Convert(typ.Elem()).LLVMValue(), valuePtr)
}
}
m := c.NewValue(ptr, types.NewPointer(origtyp))
return m.makePointee()
case *types.Struct:
values := valuelist
llvmtyp := c.types.ToLLVM(typ)
ptr := c.createTypeMalloc(llvmtyp)
if valuemap != nil {
for key, value := range valuemap {
index := fieldIndex(typ, key.(string))
for len(values) <= index {
values = append(values, nil)
}
values[index] = value
}
}
for i, value := range values {
if value != nil {
elttype := typ.Field(i).Type
llvm_value := value.Convert(elttype).LLVMValue()
ptr := c.builder.CreateStructGEP(ptr, i, "")
c.builder.CreateStore(llvm_value, ptr)
}
}
m := c.NewValue(ptr, types.NewPointer(origtyp))
return m.makePointee()
case *types.Map:
value := llvm.ConstNull(c.types.ToLLVM(typ))
// TODO initialise map
return c.NewValue(value, origtyp)
}
panic(fmt.Sprint("Unhandled type kind: ", typ))
}