MCPcopy Index your code
hub / github.com/tinygo-org/tinygo / createExpr

Method createExpr

compiler/compiler.go:2159–2634  ·  view source on GitHub ↗

createExpr translates a Go SSA expression to LLVM IR. This can be zero, one, or multiple LLVM IR instructions and/or runtime calls.

(expr ssa.Value)

Source from the content-addressed store, hash-verified

2157// createExpr translates a Go SSA expression to LLVM IR. This can be zero, one,
2158// or multiple LLVM IR instructions and/or runtime calls.
2159func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
2160 if _, ok := b.locals[expr]; ok {
2161 // sanity check
2162 panic("instruction has already been created: " + expr.String())
2163 }
2164
2165 switch expr := expr.(type) {
2166 case *ssa.Alloc:
2167 typ := b.getLLVMType(expr.Type().Underlying().(*types.Pointer).Elem())
2168 size := b.targetData.TypeAllocSize(typ)
2169 // Move all "large" allocations to the heap.
2170 if expr.Heap || size > b.MaxStackAlloc {
2171 // Calculate ^uintptr(0)
2172 maxSize := llvm.ConstNot(llvm.ConstInt(b.uintptrType, 0, false)).ZExtValue()
2173 if size > maxSize {
2174 // Size would be truncated if truncated to uintptr.
2175 return llvm.Value{}, b.makeError(expr.Pos(), fmt.Sprintf("value is too big (%v bytes)", size))
2176 }
2177 sizeValue := llvm.ConstInt(b.uintptrType, size, false)
2178 layoutValue := b.createObjectLayout(typ, expr.Pos())
2179 buf := b.createRuntimeCall("alloc", []llvm.Value{sizeValue, layoutValue}, expr.Comment)
2180 align := b.targetData.ABITypeAlignment(typ)
2181 buf.AddCallSiteAttribute(0, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("align"), uint64(align)))
2182 return buf, nil
2183 } else {
2184 buf := llvmutil.CreateEntryBlockAlloca(b.Builder, typ, expr.Comment)
2185 if b.targetData.TypeAllocSize(typ) != 0 {
2186 b.CreateStore(llvm.ConstNull(typ), buf) // zero-initialize var
2187 }
2188 return buf, nil
2189 }
2190 case *ssa.BinOp:
2191 x := b.getValue(expr.X, getPos(expr))
2192 y := b.getValue(expr.Y, getPos(expr))
2193 return b.createBinOp(expr.Op, expr.X.Type(), expr.Y.Type(), x, y, expr.Pos())
2194 case *ssa.Call:
2195 return b.createFunctionCall(expr.Common())
2196 case *ssa.ChangeInterface:
2197 // Do not change between interface types: always use the underlying
2198 // (concrete) type in the type number of the interface. Every method
2199 // call on an interface will do a lookup which method to call.
2200 // This is different from how the official Go compiler works, because of
2201 // heap allocation and because it's easier to implement, see:
2202 // https://research.swtch.com/interfaces
2203 return b.getValue(expr.X, getPos(expr)), nil
2204 case *ssa.ChangeType:
2205 // This instruction changes the type, but the underlying value remains
2206 // the same. This is often a no-op, but sometimes we have to change the
2207 // LLVM type as well.
2208 x := b.getValue(expr.X, getPos(expr))
2209 llvmType := b.getLLVMType(expr.Type())
2210 if x.Type() == llvmType {
2211 // Different Go type but same LLVM type (for example, named int).
2212 // This is the common case.
2213 return x, nil
2214 }
2215 // Figure out what kind of type we need to cast.
2216 switch llvmType.TypeKind() {

Callers 1

createInstructionMethod · 0.95

Calls 15

TypeMethod · 0.95
createRuntimeCallMethod · 0.95
getValueMethod · 0.95
createBinOpMethod · 0.95
createFunctionCallMethod · 0.95
createConvertMethod · 0.95
getChanSelectResultMethod · 0.95
createNilCheckMethod · 0.95
extendIntegerMethod · 0.95
createTemporaryAllocaMethod · 0.95
emitLifetimeEndMethod · 0.95

Tested by

no test coverage detected