@@ -29,6 +29,35 @@ func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) {
29
29
return b .CreateCall (fnType , target , nil , "" ), nil
30
30
}
31
31
32
+ // collectInlineAsmRegisters extracts register values from the map referrers,
33
+ // stopping when it encounters the AsmFull call itself to avoid processing
34
+ // MapUpdate operations that happen after the call.
35
+ func (b * builder ) collectInlineAsmRegisters (instr * ssa.CallCommon , registerMap * ssa.MakeMap ) (map [string ]llvm.Value , error ) {
36
+ registers := map [string ]llvm.Value {}
37
+ for _ , r := range * registerMap .Referrers () {
38
+ switch r := r .(type ) {
39
+ case * ssa.DebugRef :
40
+ // ignore
41
+ case * ssa.MapUpdate :
42
+ if r .Block () != registerMap .Block () {
43
+ return nil , b .makeError (instr .Pos (), "register value map must be created in the same basic block" )
44
+ }
45
+ key := constant .StringVal (r .Key .(* ssa.Const ).Value )
46
+ registers [key ] = b .getValue (r .Value .(* ssa.MakeInterface ).X , getPos (instr ))
47
+ case * ssa.Call :
48
+ if r .Common () == instr {
49
+ // Stop processing when we encounter the AsmFull call itself
50
+ // to avoid including MapUpdate operations that happen after the call
51
+ return registers , nil
52
+ }
53
+ default :
54
+ return nil , b .makeError (instr .Pos (), "don't know how to handle argument to inline assembly: " + r .String ())
55
+ }
56
+ }
57
+
58
+ return registers , nil
59
+ }
60
+
32
61
// This is a compiler builtin, which allows assembly to be called in a flexible
33
62
// way.
34
63
//
@@ -46,28 +75,13 @@ func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) {
46
75
func (b * builder ) createInlineAsmFull (instr * ssa.CallCommon ) (llvm.Value , error ) {
47
76
asmString := constant .StringVal (instr .Args [0 ].(* ssa.Const ).Value )
48
77
registers := map [string ]llvm.Value {}
78
+
49
79
if registerMap , ok := instr .Args [1 ].(* ssa.MakeMap ); ok {
50
- for _ , r := range * registerMap .Referrers () {
51
- switch r := r .(type ) {
52
- case * ssa.DebugRef :
53
- // ignore
54
- case * ssa.MapUpdate :
55
- if r .Block () != registerMap .Block () {
56
- return llvm.Value {}, b .makeError (instr .Pos (), "register value map must be created in the same basic block" )
57
- }
58
- key := constant .StringVal (r .Key .(* ssa.Const ).Value )
59
- registers [key ] = b .getValue (r .Value .(* ssa.MakeInterface ).X , getPos (instr ))
60
- case * ssa.Call :
61
- if r .Common () == instr {
62
- // Stop processing when we encounter the AsmFull call itself
63
- // to avoid including MapUpdate operations that happen after the call
64
- goto done
65
- }
66
- default :
67
- return llvm.Value {}, b .makeError (instr .Pos (), "don't know how to handle argument to inline assembly: " + r .String ())
68
- }
80
+ var err error
81
+ registers , err = b .collectInlineAsmRegisters (instr , registerMap )
82
+ if err != nil {
83
+ return llvm.Value {}, err
69
84
}
70
- done:
71
85
}
72
86
// TODO: handle dollar signs in asm string
73
87
registerNumbers := map [string ]int {}
0 commit comments