164
164
# Same as cgen, for easier genAssignment comparison
165
165
TAssignmentFlag = enum
166
166
needToCopy
167
+ needToCopySinkParam
167
168
168
169
TAssignmentFlags = set [TAssignmentFlag ]
169
170
@@ -4734,6 +4735,29 @@ proc callAssign(
4734
4735
fty = f.globalGetValueType ()
4735
4736
discard g.b.buildCall2 (fty, f, [dest, src, shallow], " " )
4736
4737
4738
+ const noUnwinds = toHashSet (
4739
+ [
4740
+ (" ansi_c" , " c_memchr" ),
4741
+ (" ansi_c" , " c_memcmp" ),
4742
+ (" ansi_c" , " c_memcpy" ),
4743
+ (" ansi_c" , " c_memmove" ),
4744
+ (" ansi_c" , " c_memset" ),
4745
+ (" ansi_c" , " c_strcmp" ),
4746
+ (" ansi_c" , " c_strlen" ),
4747
+ (" ansi_c" , " c_strstr" ),
4748
+ (" ansi_c" , " c_abort" ),
4749
+ (" ansi_c" , " c_malloc" ),
4750
+ (" ansi_c" , " c_calloc" ),
4751
+ (" ansi_c" , " c_free" ),
4752
+ (" ansi_c" , " c_realloc" ),
4753
+ (" nlvm_system" , " mmap" ),
4754
+ (" nlvm_system" , " munmap" ),
4755
+ (" system" , " mmap" ),
4756
+ (" system" , " munmap" ),
4757
+ (" system" , " rawQuit" ),
4758
+ ]
4759
+ )
4760
+
4737
4761
proc addNimFunction (g: LLGen , sym: PSym ): llvm.ValueRef =
4738
4762
# # Add a function prototype for a nim function to the given module
4739
4763
let
@@ -4743,6 +4767,18 @@ proc addNimFunction(g: LLGen, sym: PSym): llvm.ValueRef =
4743
4767
4744
4768
f = g.addNimFunction (name, ty)
4745
4769
4770
+ if sfImportc in sym.flags:
4771
+ if typ[0 ] != nil and typ[0 ].kind in {tyTuple, tyObject} and
4772
+ g.config.getSize (typ[0 ]) <= 16 :
4773
+ # TODO https://github.com/llvm/llvm-project/blob/6cbc64ed922cc69bc292d394ba5c681fa309f404/clang/lib/CodeGen/Targets/X86.cpp#L1783
4774
+ # TODO https://github.com/ziglang/zig/pull/9443
4775
+ g.config.message (
4776
+ sym.info,
4777
+ warnUser,
4778
+ " TODO: C ABI for small struct returns not implemented - there may be issues: " &
4779
+ $ name,
4780
+ )
4781
+
4746
4782
if sfNoReturn in sym.flags:
4747
4783
f.addFuncAttribute (g.attrNoReturn)
4748
4784
@@ -4761,64 +4797,94 @@ proc addNimFunction(g: LLGen, sym: PSym): llvm.ValueRef =
4761
4797
]:
4762
4798
f.addFuncAttribute (g.attrCold)
4763
4799
4764
- if (sym.originatingModule.name.s, sym.name.s) in
4765
- [(" system" , " quit" ), (" ansi_c" , " c_abort" )]:
4800
+ # C functions known to not raise exceptions - can't enable for all importc
4801
+ # functions because they might take a callback or use a global to cause
4802
+ # unwinding :/
4803
+ if (sym.originatingModule.name.s, sym.name.s) in noUnwinds:
4766
4804
f.addFuncAttribute (g.attrNoUnwind)
4767
4805
4768
4806
if sym.originatingModule.name.s == " system" and g.config.selectedGC notin {gcRegions}:
4769
- if sym.name.s in [" allocImpl" , " allocSharedImpl" ]:
4807
+ template allocsize (size, count: uint32 ): uint64 =
4808
+ uint64 (size) shl 32 or uint64 (count)
4809
+
4810
+ template allocsize (size: uint32 ): uint64 =
4811
+ allocsize (size, not 0 'u32 )
4812
+
4813
+ # TODO this constant should be set based on the _target_, not `nlvm` itself
4814
+ const MemAlign =
4815
+ when defined (nimMemAlignTiny):
4816
+ 4
4817
+ elif defined (useMalloc):
4818
+ when defined (amd64): 16 else : 8
4819
+ else :
4820
+ 16
4821
+
4822
+ const allocDefaultAlignedFns = toTable (
4823
+ {
4824
+ " allocImpl" : (AllocFnKindUninitialized , allocsize (0 )),
4825
+ " allocSharedImpl" : (AllocFnKindUninitialized , allocsize (0 )),
4826
+ " alloc0Impl" : (AllocFnKindZeroed , allocsize (0 )),
4827
+ " allocShared0Impl" : (AllocFnKindZeroed , allocsize (0 )),
4828
+ " newObj" : (AllocFnKindZeroed , allocsize (1 )),
4829
+ " newObjRC1" : (AllocFnKindZeroed , allocsize (1 )),
4830
+ " newObjNoInit" : (AllocFnKindUninitialized , allocsize (1 )),
4831
+ " rawNewObj" : (AllocFnKindUninitialized , allocsize (1 )),
4832
+ " alloc" : (AllocFnKindUninitialized , allocsize (1 )),
4833
+ " rawAlloc" : (AllocFnKindUninitialized , allocsize (1 )),
4834
+ }
4835
+ )
4836
+
4837
+ const allocParamAlignedFns = toTable (
4838
+ {
4839
+ " nimNewObj" : (AllocFnKindZeroed , allocsize (0 ), 1 ),
4840
+ " nimNewObjUninit" : (AllocFnKindUninitialized , allocsize (0 ), 1 ),
4841
+ " alignedAlloc" : (AllocFnKindUninitialized , allocsize (0 ), 1 ),
4842
+ " alignedAlloc0" : (AllocFnKindZeroed , allocsize (0 ), 1 ),
4843
+ }
4844
+ )
4845
+
4846
+ if sym.name.s in allocDefaultAlignedFns:
4847
+ let attrs = allocDefaultAlignedFns[sym.name.s]
4770
4848
f.addFuncAttribute (g.lc.createStringAttribute (" alloc-family" , " nimgc" ))
4771
4849
f.addFuncAttribute (
4772
- g.lc.createEnumAttribute (
4773
- attrAllockind, AllocFnKindAlloc or AllocFnKindUninitialized
4774
- )
4850
+ g.lc.createEnumAttribute (attrAllockind, AllocFnKindAlloc or attrs[0 ])
4775
4851
)
4776
- f.addFuncAttribute (g.lc.createEnumAttribute (attrAllocsize, cast [ uint32 ]( - 1 ) ))
4852
+ f.addFuncAttribute (g.lc.createEnumAttribute (attrAllocsize, attrs[ 1 ] ))
4777
4853
f.addAttributeAtIndex (
4778
- AttributeIndex (AttributeReturnIndex ), g.lc.createEnumAttribute (attrAlign, 16 )
4854
+ AttributeIndex (AttributeReturnIndex ),
4855
+ g.lc.createEnumAttribute (attrAlign, MemAlign ),
4779
4856
)
4780
4857
f.addAttributeAtIndex (AttributeIndex (AttributeReturnIndex ), g.attrNonnull)
4781
4858
f.addAttributeAtIndex (AttributeIndex (AttributeReturnIndex ), g.attrNoalias)
4782
- elif sym.name.s in [" alloc0Impl" , " allocShared0Impl" ]:
4859
+ elif sym.name.s in allocParamAlignedFns:
4860
+ let attrs = allocParamAlignedFns[sym.name.s]
4783
4861
f.addFuncAttribute (g.lc.createStringAttribute (" alloc-family" , " nimgc" ))
4784
4862
f.addFuncAttribute (
4785
- g.lc.createEnumAttribute (attrAllockind, AllocFnKindAlloc or AllocFnKindZeroed )
4863
+ g.lc.createEnumAttribute (
4864
+ attrAllockind, AllocFnKindAlloc or AllocFnKindAligned or attrs[0 ]
4865
+ )
4786
4866
)
4787
- f.addFuncAttribute (g.lc.createEnumAttribute (attrAllocsize, cast [ uint32 ]( - 1 ) ))
4867
+ f.addFuncAttribute (g.lc.createEnumAttribute (attrAllocsize, attrs[ 1 ] ))
4788
4868
f.addAttributeAtIndex (
4789
- AttributeIndex (AttributeReturnIndex ), g.lc.createEnumAttribute (attrAlign, 16 )
4869
+ AttributeIndex (attrs[ 2 ] + 1 ), g.lc.createEnumAttribute (attrAllocalign, 0 )
4790
4870
)
4791
4871
f.addAttributeAtIndex (AttributeIndex (AttributeReturnIndex ), g.attrNonnull)
4792
4872
f.addAttributeAtIndex (AttributeIndex (AttributeReturnIndex ), g.attrNoalias)
4793
- elif sym.name.s in [" alloc0" , " newObj" , " newObjRC1" , " rawAlloc0" , " allocShared0" ]:
4873
+ elif sym.name.s in [" dealloc" , " deallocShared" ]:
4874
+ f.addFuncAttribute (g.attrNoUnwind)
4794
4875
f.addFuncAttribute (g.lc.createStringAttribute (" alloc-family" , " nimgc" ))
4795
- f.addFuncAttribute (
4796
- g.lc.createEnumAttribute (attrAllockind, AllocFnKindAlloc or AllocFnKindZeroed )
4797
- )
4798
- f.addFuncAttribute (
4799
- g.lc.createEnumAttribute (attrAllocsize, uint64 (1 shl 32 ) + cast [uint32 ](- 1 ))
4800
- )
4876
+ f.addFuncAttribute (g.lc.createEnumAttribute (attrAllockind, AllocFnKindFree ))
4877
+
4801
4878
f.addAttributeAtIndex (
4802
- AttributeIndex (AttributeReturnIndex ), g.lc.createEnumAttribute (attrAlign, 16 )
4879
+ AttributeIndex (typ.len - 1 ), g.lc.createEnumAttribute (attrAllocptr, 0 )
4803
4880
)
4804
- f.addAttributeAtIndex (AttributeIndex (AttributeReturnIndex ), g.attrNonnull)
4805
- f.addAttributeAtIndex (AttributeIndex (AttributeReturnIndex ), g.attrNoalias)
4806
- elif sym.name.s in
4807
- [" alloc" , " rawAlloc" , " newObjNoInit" , " rawNewObj" , " rawAlloc" , " allocShared" ]:
4881
+ elif sym.name.s in [" rawDealloc" ]:
4882
+ f.addFuncAttribute (g.attrNoUnwind)
4808
4883
f.addFuncAttribute (g.lc.createStringAttribute (" alloc-family" , " nimgc" ))
4809
- f.addFuncAttribute (
4810
- g.lc.createEnumAttribute (
4811
- attrAllockind, AllocFnKindAlloc or AllocFnKindUninitialized
4812
- )
4813
- )
4814
- f.addFuncAttribute (
4815
- g.lc.createEnumAttribute (attrAllocsize, uint64 (1 shl 32 ) + cast [uint32 ](- 1 ))
4816
- )
4884
+ f.addFuncAttribute (g.lc.createEnumAttribute (attrAllockind, AllocFnKindFree ))
4817
4885
f.addAttributeAtIndex (
4818
- AttributeIndex (AttributeReturnIndex ), g.lc.createEnumAttribute (attrAlign, 16 )
4886
+ AttributeIndex (2 ), g.lc.createEnumAttribute (attrAllocptr, 0 )
4819
4887
)
4820
- f.addAttributeAtIndex (AttributeIndex (AttributeReturnIndex ), g.attrNonnull)
4821
- f.addAttributeAtIndex (AttributeIndex (AttributeReturnIndex ), g.attrNoalias)
4822
4888
4823
4889
f
4824
4890
@@ -5388,7 +5454,7 @@ proc genBoundsCheckArray(g: LLGen, arr, firstOrd, lastOrd, a, b: llvm.ValueRef)
5388
5454
5389
5455
proc buildLoadVar (g: LLGen , typ: PType , v: llvm.ValueRef ): llvm.ValueRef =
5390
5456
if typ.skipTypes (abstractInst).kind in {tyVar, tyLent}:
5391
- g.b.buildLoad2 (g.ptrTy , v)
5457
+ g.b.buildLoad2 (g.llType ( last (typ. skipTypes (abstractInst))) , v)
5392
5458
else :
5393
5459
v
5394
5460
@@ -5427,14 +5493,12 @@ proc genOpenArrayConv(
5427
5493
else :
5428
5494
axp.v
5429
5495
v = g.buildLoadVar (n.typ, ax)
5430
-
5431
5496
(g.getNimSeqDataPtr (seqTy, v), g.loadNimSeqLen (v))
5432
5497
of tyOpenArray, tyVarargs:
5433
- let ax = g.buildLoadVar (n.typ, g.genNode (n, false ).v)
5434
-
5498
+ let ax = g.buildLoadVar (n.typ, g.genNode (n, true ).v)
5435
5499
(
5436
- g.b.buildLoad2 (g.ptrTy, g. buildOpenArrayDataGEP ( ax)),
5437
- g.b.buildLoad2 (g.intTy, g. buildOpenArrayLenGEP ( ax)),
5500
+ g.b.buildExtractValue (ax, 0 , g. nn ( " p " , ax)),
5501
+ g.b.buildExtractValue (ax, 1 , g. nn ( " l " , ax)),
5438
5502
)
5439
5503
of tyArray, tyUncheckedArray:
5440
5504
var v = g.genNode (n, true ).v
@@ -5798,9 +5862,8 @@ proc genAssignment(g: LLGen, dest, src: LLValue, typ: PType, flags: TAssignmentF
5798
5862
of tyString:
5799
5863
if optSeqDestructors in g.config.globalOptions:
5800
5864
discard g.b.buildStore (src.v, dest.v)
5801
- elif ({needToCopy} * flags == {} and src.storage != OnStatic ) or canMove (
5802
- g, src.lode
5803
- ):
5865
+ elif ({needToCopy, needToCopySinkParam} * flags == {} and src.storage != OnStatic ) or
5866
+ canMove (g, src.lode):
5804
5867
g.genRefAssign (dest, src.v)
5805
5868
else :
5806
5869
if (dest.storage == OnStack and g.config.selectedGC != gcGo) or
@@ -5961,9 +6024,15 @@ proc genConstBracket(g: LLGen, n: PNode): llvm.ValueRef =
5961
6024
for i, s in n.sons:
5962
6025
vals[i] = g.genConstInitializer (s)
5963
6026
let s = constArray (et, vals)
5964
- if typ.kind in {tyArray, tyUncheckedArray}:
6027
+ case typ.kind
6028
+ of tyArray, tyUncheckedArray:
5965
6029
s
5966
- else :
6030
+ of tyOpenArray:
6031
+ let lit = g.m.addPrivateConstant (s.typeOfX, g.nn (" .oa" , n))
6032
+ lit.setInitializer (s)
6033
+
6034
+ llvm.constNamedStruct (g.llOpenArrayType (), [lit, g.constInt64 (vals.len)])
6035
+ of tySequence:
5967
6036
let
5968
6037
ll = g.constNimInt (vals.len)
5969
6038
cap = g.constNimInt (vals.len + g.strLitFlag)
@@ -5980,6 +6049,8 @@ proc genConstBracket(g: LLGen, n: PNode): llvm.ValueRef =
5980
6049
lit = g.m.addPrivateConstant (payload.typeOfX, g.nn (" .seq" , n))
5981
6050
lit.setInitializer (payload)
5982
6051
lit
6052
+ else :
6053
+ raiseAssert " Unexpected const bracket: " & $ typ.kind
5983
6054
5984
6055
proc genConstObjConstr (g: LLGen , n: PNode ): llvm.ValueRef =
5985
6056
let
@@ -6748,6 +6819,8 @@ proc genMagicLengthStr(g: LLGen, n: PNode): LLValue =
6748
6819
fty = llvm.functionType (g.csizetTy, [g.primitives[tyCString]])
6749
6820
f = g.m.getOrInsertFunction (" strlen" , fty)
6750
6821
6822
+ f.addFuncAttribute (g.attrNoUnwind)
6823
+
6751
6824
let v1 = g.buildTruncOrExt (
6752
6825
g.b.buildCall2 (fty, f, [v], g.nn (" str.len.call" , n)), g.primitives[tyInt], false
6753
6826
)
@@ -7790,13 +7863,49 @@ proc genMagicMove(g: LLGen, n: PNode, load: bool): LLValue =
7790
7863
7791
7864
g.buildStoreNull (ty, tmpx.v)
7792
7865
g.genObjectInit (n[1 ].typ, tmpx.v)
7793
- let flags =
7794
- if not canMove (g, n[1 ]):
7795
- {needToCopy}
7866
+ if g.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}:
7867
+ g.genAssignment (tmpx, g.maybeLoadValue (ty, ax, lx), n[1 ].typ, {})
7868
+ var op = getAttachedOp (g.graph, n.typ, attachedWasMoved)
7869
+ if op == nil :
7870
+ g.callReset (n[1 ].skipAddr.typ, ax)
7796
7871
else :
7797
- {}
7798
- g.genAssignment (tmpx, g.maybeLoadValue (ty, ax, lx), n[1 ].typ, flags)
7799
- g.callReset (n[1 ].skipAddr.typ, ax)
7872
+ case skipTypes (n[1 ].skipAddr.typ, abstractVar + {tyStatic}).kind
7873
+ of tyOpenArray, tyVarargs:
7874
+ # todo fixme generated `wasMoved` hooks for
7875
+ # openarrays, but it probably shouldn't?
7876
+ raiseAssert " TODO"
7877
+ # var s: string
7878
+ # if reifiedOpenArray(a.lode):
7879
+ # if a.t.kind in {tyVar, tyLent}:
7880
+ # s = "$1->Field0, $1->Field1" % [rdLoc(a)]
7881
+ # else:
7882
+ # s = "$1.Field0, $1.Field1" % [rdLoc(a)]
7883
+ # else:
7884
+ # s = "$1, $1Len_0" % [rdLoc(a)]
7885
+ # linefmt(p, cpsStmts, "$1($2);$n", [rdLoc(b), s])
7886
+ else :
7887
+ let
7888
+ f = g.genFunctionWithBody (op).v
7889
+ fty = f.globalGetValueType ()
7890
+ discard g.b.buildCall2 (fty, f, [ax.v], " " )
7891
+ else :
7892
+ if n[1 ].kind == nkSym and isSinkParam (n[1 ].sym):
7893
+ let ty2 = g.llType (n[1 ].typ.skipTypes ({tySink}))
7894
+ let tmp2 =
7895
+ LLValue (v: g.localAlloca (ty2, g.nn (" move.tmp2" , n[1 ])), storage: OnStack )
7896
+
7897
+ g.buildStoreNull (ty2, tmp2.v)
7898
+ g.genObjectInit (n[1 ].typ.skipTypes ({tySink}), tmp2.v)
7899
+
7900
+ g.genAssignment (
7901
+ tmp2, g.maybeLoadValue (ty, ax, lx), n[1 ].typ, {needToCopySinkParam}
7902
+ )
7903
+ g.genAssignment (tmpx, g.buildLoadValue (ty2, tmp2), n[1 ].typ, {})
7904
+ g.callReset (n[1 ].typ.skipTypes ({tySink}), tmp2)
7905
+ else :
7906
+ g.genAssignment (tmpx, g.maybeLoadValue (ty, ax, lx), n[1 ].typ, {})
7907
+ g.callReset (n[1 ].skipAddr.typ, ax)
7908
+
7800
7909
g.maybeLoadValue (ty, tmpx, load)
7801
7910
7802
7911
proc genMagicDestroy (g: LLGen , n: PNode ) =
0 commit comments