github.com/llir/llvm@v0.3.6/asm/const.go (about) 1 package asm 2 3 import ( 4 "fmt" 5 6 "github.com/llir/ll/ast" 7 "github.com/llir/llvm/internal/enc" 8 "github.com/llir/llvm/ir" 9 "github.com/llir/llvm/ir/constant" 10 "github.com/llir/llvm/ir/types" 11 "github.com/pkg/errors" 12 ) 13 14 // === [ Translate AST to IR ] ================================================= 15 16 // irConstant translates the AST constant into an equivalent IR constant. 17 func (gen *generator) irConstant(t types.Type, old ast.Constant) (constant.Constant, error) { 18 switch old := old.(type) { 19 case *ast.BoolConst: 20 return gen.irBoolConst(t, old) 21 case *ast.IntConst: 22 return gen.irIntConst(t, old) 23 case *ast.FloatConst: 24 return gen.irFloatConst(t, old) 25 case *ast.NullConst: 26 return gen.irNullConst(t, old) 27 case *ast.NoneConst: 28 return gen.irNoneConst(t, old) 29 case *ast.StructConst: 30 return gen.irStructConst(t, old) 31 case *ast.ArrayConst: 32 return gen.irArrayConst(t, old) 33 case *ast.CharArrayConst: 34 return gen.irCharArrayConst(t, old) 35 case *ast.VectorConst: 36 return gen.irVectorConst(t, old) 37 case *ast.ZeroInitializerConst: 38 return constant.NewZeroInitializer(t), nil 39 case *ast.UndefConst: 40 return constant.NewUndef(t), nil 41 case *ast.PoisonConst: 42 return constant.NewPoison(t), nil 43 case *ast.BlockAddressConst: 44 return gen.irBlockAddressConst(t, old) 45 case *ast.DSOLocalEquivalentConst: 46 return gen.irDSOLocalEquivalentConst(t, old) 47 case *ast.NoCFIConst: 48 return gen.irNoCFIConst(t, old) 49 case *ast.GlobalIdent: 50 ident := globalIdent(*old) 51 c, ok := gen.new.globals[ident] 52 if !ok { 53 return nil, errors.Errorf("unable to locate global identifier %q", ident.Ident()) 54 } 55 return c, nil 56 case ast.ConstantExpr: 57 return gen.irConstantExpr(t, old) 58 default: 59 panic(fmt.Errorf("support for AST constant %T not yet implemented", old)) 60 } 61 } 62 63 // irTypeConst translates the AST type-constant pair into an equivalent IR 64 // constant. 65 func (gen *generator) irTypeConst(old ast.TypeConst) (constant.Constant, error) { 66 // Type. 67 typ, err := gen.irType(old.Typ()) 68 if err != nil { 69 return nil, errors.WithStack(err) 70 } 71 // Constant. 72 return gen.irConstant(typ, old.Val()) 73 } 74 75 // --- [ Boolean constants ] --------------------------------------------------- 76 77 // irBoolConst translates the AST boolean constant into an equivalent IR integer 78 // constant. 79 func (gen *generator) irBoolConst(t types.Type, old *ast.BoolConst) (*constant.Int, error) { 80 typ, ok := t.(*types.IntType) 81 if !ok { 82 return nil, errors.Errorf("invalid type of boolean constant; expected *types.IntType, got %T", t) 83 } 84 if !typ.Equal(types.I1) { 85 return nil, errors.Errorf("boolean type mismatch; expected %q, got %q", types.I1, typ) 86 } 87 return constant.NewBool(boolLit(old.BoolLit())), nil 88 } 89 90 // --- [ Integer constants ] --------------------------------------------------- 91 92 // irIntConst translates the AST integer constant into an equivalent IR integer 93 // constant. 94 func (gen *generator) irIntConst(t types.Type, old *ast.IntConst) (*constant.Int, error) { 95 typ, ok := t.(*types.IntType) 96 if !ok { 97 line, col := old.LineColumn() 98 return nil, errors.Errorf("%d:%d: invalid type of integer constant; expected *types.IntType, got %T", line, col, t) 99 } 100 s := old.IntLit().Text() 101 return constant.NewIntFromString(typ, s) 102 } 103 104 // --- [ Floating-point constants ] -------------------------------------------- 105 106 // irFloatConst translates the AST floating-point constant into an equivalent IR 107 // floating-point constant. 108 func (gen *generator) irFloatConst(t types.Type, old *ast.FloatConst) (*constant.Float, error) { 109 typ, ok := t.(*types.FloatType) 110 if !ok { 111 return nil, errors.Errorf("invalid type of floating-point constant; expected *types.FloatType, got %T", t) 112 } 113 s := old.FloatLit().Text() 114 return constant.NewFloatFromString(typ, s) 115 } 116 117 // --- [ Null pointer constants ] ---------------------------------------------- 118 119 // irNullConst translates the AST null pointer constant into an equivalent IR 120 // null pointer constant. 121 func (gen *generator) irNullConst(t types.Type, old *ast.NullConst) (*constant.Null, error) { 122 typ, ok := t.(*types.PointerType) 123 if !ok { 124 return nil, errors.Errorf("invalid type of null pointer constant; expected *types.PointerType, got %T", t) 125 } 126 return constant.NewNull(typ), nil 127 } 128 129 // --- [ Token constants ] ----------------------------------------------------- 130 131 // irNoneConst translates the AST none token constant into an equivalent IR none 132 // token constant. 133 func (gen *generator) irNoneConst(t types.Type, old *ast.NoneConst) (constant.Constant, error) { 134 if !t.Equal(types.Token) { 135 return nil, errors.Errorf("invalid type of none token constant; expected %q, got %q", types.Token, t) 136 } 137 return constant.None, nil 138 } 139 140 // --- [ Struct constants ] ---------------------------------------------------- 141 142 // irStructConst translates the AST struct constant into an equivalent IR struct 143 // constant. 144 func (gen *generator) irStructConst(t types.Type, old *ast.StructConst) (*constant.Struct, error) { 145 typ, ok := t.(*types.StructType) 146 if !ok { 147 return nil, errors.Errorf("invalid type of struct constant; expected *types.StructType, got %T", t) 148 } 149 var fields []constant.Constant 150 if oldFields := old.Fields(); len(oldFields) > 0 { 151 fields = make([]constant.Constant, len(oldFields)) 152 for i, oldField := range oldFields { 153 field, err := gen.irTypeConst(oldField) 154 if err != nil { 155 return nil, errors.WithStack(err) 156 } 157 fields[i] = field 158 } 159 } 160 c := constant.NewStruct(typ, fields...) 161 return c, nil 162 } 163 164 // --- [ Array constants ] ----------------------------------------------------- 165 166 // irArrayConst translates the AST array constant into an equivalent IR array 167 // constant. 168 func (gen *generator) irArrayConst(t types.Type, old *ast.ArrayConst) (*constant.Array, error) { 169 typ, ok := t.(*types.ArrayType) 170 if !ok { 171 return nil, errors.Errorf("invalid type of array constant; expected *types.ArrayType, got %T", t) 172 } 173 oldElems := old.Elems() 174 if len(oldElems) == 0 { 175 typ := types.NewArray(0, typ.ElemType) 176 if !t.Equal(typ) { 177 return nil, errors.Errorf("array type mismatch; expected %q, got %q", typ, t) 178 } 179 return &constant.Array{Typ: typ}, nil 180 } 181 elems := make([]constant.Constant, len(oldElems)) 182 for i, oldElem := range oldElems { 183 elem, err := gen.irTypeConst(oldElem) 184 if err != nil { 185 return nil, errors.WithStack(err) 186 } 187 elems[i] = elem 188 } 189 c := constant.NewArray(typ, elems...) 190 return c, nil 191 } 192 193 // irCharArrayConst translates the AST character array constant into an 194 // equivalent IR character array constant. 195 func (gen *generator) irCharArrayConst(t types.Type, old *ast.CharArrayConst) (*constant.CharArray, error) { 196 data := enc.Unquote(old.Val().Text()) 197 c := constant.NewCharArray(data) 198 if !t.Equal(c.Typ) { 199 return nil, errors.Errorf("character array type mismatch; expected %q, got %q (unquoted_data=`%s`, orig_data=`%s`)", c.Typ, t, data, old.Val().Text()) 200 } 201 return c, nil 202 } 203 204 // --- [ Vector constants ] ---------------------------------------------------- 205 206 // irVectorConst translates the AST vector constant into an equivalent IR vector 207 // constant. 208 func (gen *generator) irVectorConst(t types.Type, old *ast.VectorConst) (*constant.Vector, error) { 209 typ, ok := t.(*types.VectorType) 210 if !ok { 211 return nil, errors.Errorf("invalid type of vector constant; expected *types.VectorType, got %T", t) 212 } 213 oldElems := old.Elems() 214 if len(oldElems) == 0 { 215 return nil, errors.New("zero element vector is illegal") 216 } 217 elems := make([]constant.Constant, len(oldElems)) 218 for i, oldElem := range oldElems { 219 elem, err := gen.irTypeConst(oldElem) 220 if err != nil { 221 return nil, errors.WithStack(err) 222 } 223 elems[i] = elem 224 } 225 c := constant.NewVector(typ, elems...) 226 return c, nil 227 } 228 229 // --- [ Addresses of basic blocks ] ------------------------------------------- 230 231 // irBlockAddressConst translates the AST blockaddress constant into an 232 // equivalent IR blockaddress constant. 233 func (gen *generator) irBlockAddressConst(t types.Type, old *ast.BlockAddressConst) (*constant.BlockAddress, error) { 234 // Function. 235 funcName := globalIdent(old.Func()) 236 v, ok := gen.new.globals[funcName] 237 if !ok { 238 return nil, errors.Errorf("unable to locate global identifier %q", funcName) 239 } 240 f, ok := v.(*ir.Func) 241 if !ok { 242 return nil, errors.Errorf("invalid function type; expected *ir.Func, got %T", v) 243 } 244 // Basic block. 245 blockIdent := localIdent(old.Block()) 246 // Add dummy basic block to track the name recorded by the AST. Resolve the 247 // proper basic block after translation of function bodies and assignment of 248 // local IDs. 249 block := &ir.Block{ 250 LocalIdent: blockIdent, 251 } 252 c := constant.NewBlockAddress(f, block) 253 gen.todo = append(gen.todo, c) 254 if typ := c.Type(); !t.Equal(typ) { 255 return nil, errors.Errorf("blockaddress constant type mismatch; expected %q, got %q", typ, t) 256 } 257 return c, nil 258 } 259 260 // --- [ DSO Local Equivalent ] ------------------------------------------------ 261 262 // irDSOLocalEquivalentConst translates the AST dso_local_equivalent constant 263 // into an equivalent IR dso_local_equivalent constant. 264 func (gen *generator) irDSOLocalEquivalentConst(t types.Type, old *ast.DSOLocalEquivalentConst) (*constant.DSOLocalEquivalent, error) { 265 // Function. 266 funcName := globalIdent(old.Func()) 267 v, ok := gen.new.globals[funcName] 268 if !ok { 269 return nil, errors.Errorf("unable to locate global identifier %q", funcName) 270 } 271 var f constant.Constant 272 switch v := v.(type) { 273 case *ir.Func, *ir.IFunc, *ir.Alias: 274 f = v 275 default: 276 return nil, errors.Errorf("invalid function type; expected *ir.Func or *ir.IFunc, got %T", v) 277 } 278 c := constant.NewDSOLocalEquivalent(f) 279 if typ := c.Type(); !t.Equal(typ) { 280 return nil, errors.Errorf("dso_local_equivalent constant type mismatch; expected %q, got %q", typ, t) 281 } 282 return c, nil 283 } 284 285 // --- [ No CFI ] -------------------------------------------------------------- 286 287 // irNoCFIConst translates the AST no_cfi constant into an equivalent IR no_cfi 288 // constant. 289 func (gen *generator) irNoCFIConst(t types.Type, old *ast.NoCFIConst) (*constant.NoCFI, error) { 290 // Function. 291 funcName := globalIdent(old.Func()) 292 v, ok := gen.new.globals[funcName] 293 if !ok { 294 return nil, errors.Errorf("unable to locate global identifier %q", funcName) 295 } 296 var f constant.Constant 297 switch v := v.(type) { 298 case *ir.Func, *ir.IFunc, *ir.Alias: 299 f = v 300 default: 301 return nil, errors.Errorf("invalid function type; expected *ir.Func or *ir.IFunc, got %T", v) 302 } 303 c := constant.NewNoCFI(f) 304 if typ := c.Type(); !t.Equal(typ) { 305 return nil, errors.Errorf("no_cfi constant type mismatch; expected %q, got %q", typ, t) 306 } 307 return c, nil 308 }