Added array and struct constant generation
This commit is contained in:
parent
86ad94f17d
commit
0c8a9d995b
|
@ -26,8 +26,16 @@ func (this *generator) generateConstantDeclaration (
|
|||
// both. have single generateConstant method that converts if necessary
|
||||
// by either loading or allocating a copy on the stack.
|
||||
//
|
||||
// have a Multivalue method of types and disallow referencing of
|
||||
// non-multivalue constants.
|
||||
// Have a ConstantSupport method of Type that returns either:
|
||||
// - ConstantSupportLoc - multivalue, stored
|
||||
// - ConstantSupportVal - singlevalue, not stored
|
||||
// - ConstantSupportNone - cannot be used as a constant
|
||||
//
|
||||
// Pointers and anything with a pointer inside it must return
|
||||
// ConstantSupportNone. Aggregate types (arrays, structs) must return
|
||||
// ConstantSupportLoc if supported at all. Single value types must
|
||||
// return ConstantSupportNone if supported at all. This should be
|
||||
// checked recursively.
|
||||
|
||||
irGlobal := this.module.NewGlobal(key.LinkName(), irType)
|
||||
irGlobal.Constant = true
|
||||
|
|
|
@ -99,3 +99,53 @@ E: Int
|
|||
* -1
|
||||
[f] = [plus4 E.two]
|
||||
`)}
|
||||
|
||||
func TestConstantValueStruct (test *testing.T) {
|
||||
testString (test,
|
||||
`%"0zNZN147MN2wzMAQ6NS2dQ==::Cardinal" = type { i64, i64 }
|
||||
0zNZN147MN2wzMAQ6NS2dQ==::Cardinal.east = constant %"0zNZN147MN2wzMAQ6NS2dQ==::Cardinal" { i64, i64 } { i64 1, i64 zeroinitializer }
|
||||
0zNZN147MN2wzMAQ6NS2dQ==::Cardinal.north = constant %"0zNZN147MN2wzMAQ6NS2dQ==::Cardinal" { i64, i64 } { i64 zeroinitializer, i64 -1 }
|
||||
0zNZN147MN2wzMAQ6NS2dQ==::Cardinal.south = constant %"0zNZN147MN2wzMAQ6NS2dQ==::Cardinal" { i64, i64 } { i64 zeroinitializer, i64 1 }
|
||||
0zNZN147MN2wzMAQ6NS2dQ==::Cardinal.west = constant %"0zNZN147MN2wzMAQ6NS2dQ==::Cardinal" { i64, i64 } { i64 -1, i64 zeroinitializer }
|
||||
define void @"0zNZN147MN2wzMAQ6NS2dQ==::[f]"() {
|
||||
0:
|
||||
%1 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::Cardinal"
|
||||
%2 = load %"0zNZN147MN2wzMAQ6NS2dQ==::Cardinal", %"0zNZN147MN2wzMAQ6NS2dQ==::Cardinal" @"0zNZN147MN2wzMAQ6NS2dQ==::Cardinal.west"
|
||||
store %"0zNZN147MN2wzMAQ6NS2dQ==::Cardinal" %2, ptr %1
|
||||
ret void
|
||||
}
|
||||
`,
|
||||
`
|
||||
Cardinal: (.x:Int y:Int)
|
||||
| north = (. y: -1)
|
||||
| south = (. y: 1)
|
||||
| west = (.x: -1 )
|
||||
| east = (.x: 1 )
|
||||
[f] = {
|
||||
c:Cardinal = Cardinal.west
|
||||
}
|
||||
`)}
|
||||
|
||||
func TestConstantValueArray (test *testing.T) {
|
||||
testString (test,
|
||||
`%"0zNZN147MN2wzMAQ6NS2dQ==::Order" = type [3 x i64]
|
||||
0zNZN147MN2wzMAQ6NS2dQ==::Order.backward = constant %"0zNZN147MN2wzMAQ6NS2dQ==::Order" [3 x i64] [i64 2, i64 1, i64 0]
|
||||
0zNZN147MN2wzMAQ6NS2dQ==::Order.forward = constant %"0zNZN147MN2wzMAQ6NS2dQ==::Order" [3 x i64] [i64 0, i64 1, i64 2]
|
||||
0zNZN147MN2wzMAQ6NS2dQ==::Order.none = constant %"0zNZN147MN2wzMAQ6NS2dQ==::Order" [3 x i64] [i64 0, i64 zeroinitializer, i64 zeroinitializer]
|
||||
define void @"0zNZN147MN2wzMAQ6NS2dQ==::[f]"() {
|
||||
0:
|
||||
%1 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::Order"
|
||||
%2 = load %"0zNZN147MN2wzMAQ6NS2dQ==::Order", %"0zNZN147MN2wzMAQ6NS2dQ==::Order" @"0zNZN147MN2wzMAQ6NS2dQ==::Order.forward"
|
||||
store %"0zNZN147MN2wzMAQ6NS2dQ==::Order" %2, ptr %1
|
||||
ret void
|
||||
}
|
||||
`,
|
||||
`
|
||||
Order: 3:Int
|
||||
| none = (0)
|
||||
| forward = (0 1 2)
|
||||
| backward = (2 1 0)
|
||||
[f] = {
|
||||
o:Order = Order.forward
|
||||
}
|
||||
`)}
|
||||
|
|
|
@ -17,7 +17,7 @@ func (this *generator) generateEvaluatedInt (literal *entity.LiteralInt) (llvm.C
|
|||
case *entity.TypeFloat:
|
||||
return llvm.NewConstFloat(irType.(*llvm.TypeFloat), float64(literal.Value)), nil
|
||||
default:
|
||||
return nil, errors.New(fmt.Sprintln("int can't be used as", base))
|
||||
return nil, errors.New(fmt.Sprintln("constant int can't be used as", base))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,15 +28,64 @@ func (this *generator) generateEvaluatedFloat (literal *entity.LiteralFloat) (ll
|
|||
}
|
||||
|
||||
func (this *generator) generateEvaluatedString (literal *entity.LiteralString) (llvm.Const, error) {
|
||||
// TODO
|
||||
panic("BUG: not supported yet")
|
||||
}
|
||||
|
||||
func (this *generator) generateEvaluatedArray (literal *entity.LiteralArray) (llvm.Const, error) {
|
||||
panic("BUG: not supported yet")
|
||||
baseAny := analyzer.ReduceToBase(literal.Type())
|
||||
base, ok := baseAny.(*entity.TypeArray)
|
||||
if !ok { return nil, errors.New(fmt.Sprintln("constant array can't be used as", baseAny)) }
|
||||
|
||||
irDestTypeAny, err := this.generateType(base)
|
||||
if err != nil { return nil, err }
|
||||
irDestType := irDestTypeAny.(*llvm.TypeArray)
|
||||
irElementType, err := this.generateType(base.Element)
|
||||
if err != nil { return nil, err }
|
||||
|
||||
irArray := &llvm.ConstArray {
|
||||
Ty: irDestType,
|
||||
Elements: make([]llvm.Const, base.Length),
|
||||
}
|
||||
for index := range irArray.Elements {
|
||||
if index < len(literal.Elements) {
|
||||
irElement, err := this.generateEvaluated(literal.Elements[index])
|
||||
if err != nil { return nil, err }
|
||||
irArray.Elements[index] = irElement
|
||||
} else {
|
||||
irArray.Elements[index] = llvm.NewConstZeroInitializer(irElementType)
|
||||
}
|
||||
}
|
||||
|
||||
return irArray, nil
|
||||
}
|
||||
|
||||
func (this *generator) generateEvaluatedStruct (literal *entity.LiteralStruct) (llvm.Const, error) {
|
||||
panic("BUG: not supported yet")
|
||||
baseAny := analyzer.ReduceToBase(literal.Type())
|
||||
base, ok := baseAny.(*entity.TypeStruct)
|
||||
if !ok { return nil, errors.New(fmt.Sprintln("constant struct can't be used as", baseAny)) }
|
||||
|
||||
irDestTypeAny, err := this.generateType(base)
|
||||
if err != nil { return nil, err }
|
||||
irDestType := irDestTypeAny.(*llvm.TypeStruct)
|
||||
|
||||
irStruct := &llvm.ConstStruct {
|
||||
Ty: irDestType,
|
||||
Fields: make([]llvm.Const, len(base.Members)),
|
||||
}
|
||||
for index, member := range base.Members {
|
||||
if pair, ok := literal.MemberMap[member.Name]; ok {
|
||||
irMember, err := this.generateEvaluated(pair.Value)
|
||||
if err != nil { return nil, err }
|
||||
irStruct.Fields[index] = irMember
|
||||
} else {
|
||||
irMemberType, err := this.generateType(member.Type())
|
||||
if err != nil { return nil, err }
|
||||
irStruct.Fields[index] = llvm.NewConstZeroInitializer(irMemberType)
|
||||
}
|
||||
}
|
||||
|
||||
return irStruct, nil
|
||||
}
|
||||
|
||||
func (this *generator) generateEvaluatedBoolean (literal *entity.LiteralBoolean) (llvm.Const, error) {
|
||||
|
|
Loading…
Reference in New Issue