Completed operations
This commit is contained in:
parent
635add38e6
commit
31d5317dc8
|
@ -29,7 +29,7 @@ func (this *generator) generateAssignmentSource (
|
|||
if err != nil { return nil, err }
|
||||
ty := analyzer.ReduceToBase(to)
|
||||
|
||||
switch ty := ty.(type) {
|
||||
switch /*ty := */ty.(type) {
|
||||
case *entity.TypeInterface:
|
||||
// TODO: assign to interface
|
||||
// sourceTy := analyzer.ReduceToBase(from.Type())
|
||||
|
@ -42,9 +42,9 @@ func (this *generator) generateAssignmentSource (
|
|||
// if err != nil { return nil, err }
|
||||
// pointer := this.
|
||||
case *entity.TypeSlice:
|
||||
if fromType, ok := analyzer.ReduceToBase(from.Type()).(*entity.TypeArray); ok {
|
||||
/*if fromType, ok := analyzer.ReduceToBase(from.Type()).(*entity.TypeArray); ok {
|
||||
// TODO: convert array to slice
|
||||
}
|
||||
}*/
|
||||
}
|
||||
return source, nil
|
||||
}
|
||||
|
|
|
@ -205,42 +205,341 @@ func (this *generator) generateBitCast (cast *entity.BitCast) (llvm.Value, error
|
|||
|
||||
|
||||
func (this *generator) generateOperation (operation *entity.Operation) (llvm.Value, error) {
|
||||
nSameType := func (binary func (x, y llvm.Value) llvm.Value) (llvm.Value, error) {
|
||||
irX, err := this.generateExpression(operation.Arguments[0])
|
||||
if err != nil { return nil, err }
|
||||
for _, argument := range operation.Arguments[1:] {
|
||||
irY, err := this.generateExpression(argument)
|
||||
if err != nil { return nil, err }
|
||||
irX = binary(irX, irY)
|
||||
}
|
||||
return irX, nil
|
||||
}
|
||||
|
||||
ty := analyzer.ReduceToBase(operation.Arguments[0].Type())
|
||||
irType, err := this.generateType(ty)
|
||||
if err != nil { return nil, err }
|
||||
|
||||
switch operation.Operator {
|
||||
// math
|
||||
case entity.OperatorAdd:
|
||||
switch ty.(type) {
|
||||
case *entity.TypeInt, *entity.TypeWord:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewAdd(x, y)
|
||||
})
|
||||
case *entity.TypeFloat:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewFAdd(x, y)
|
||||
})
|
||||
}
|
||||
|
||||
case entity.OperatorSubtract:
|
||||
switch ty.(type) {
|
||||
case *entity.TypeInt, *entity.TypeWord:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewSub(x, y)
|
||||
})
|
||||
case *entity.TypeFloat:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewFSub(x, y)
|
||||
})
|
||||
}
|
||||
|
||||
case entity.OperatorMultiply:
|
||||
switch ty.(type) {
|
||||
case *entity.TypeInt, *entity.TypeWord:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewMul(x, y)
|
||||
})
|
||||
case *entity.TypeFloat:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewFMul(x, y)
|
||||
})
|
||||
}
|
||||
|
||||
case entity.OperatorDivide:
|
||||
switch ty.(type) {
|
||||
case *entity.TypeInt, *entity.TypeWord:
|
||||
if analyzer.IsUnsigned(ty) {
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewUDiv(x, y)
|
||||
})
|
||||
} else {
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewSDiv(x, y)
|
||||
})
|
||||
}
|
||||
case *entity.TypeFloat:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewFDiv(x, y)
|
||||
})
|
||||
}
|
||||
|
||||
case entity.OperatorIncrement:
|
||||
case entity.OperatorDecrement:
|
||||
irX, err := this.generateExpression(operation.Arguments[0])
|
||||
if err != nil { return nil, err }
|
||||
irType := irType.(*llvm.TypeInt)
|
||||
|
||||
switch ty.(type) {
|
||||
case *entity.TypeInt, *entity.TypeWord:
|
||||
return this.blockManager.NewAdd (
|
||||
irX,
|
||||
llvm.NewConstInt(irType, 1)), nil
|
||||
case *entity.TypeFloat:
|
||||
return this.blockManager.NewFAdd (
|
||||
irX,
|
||||
llvm.NewConstInt(irType, 1)), nil
|
||||
}
|
||||
|
||||
case entity.OperatorDecrement:
|
||||
irX, err := this.generateExpression(operation.Arguments[0])
|
||||
if err != nil { return nil, err }
|
||||
irType := irType.(*llvm.TypeInt)
|
||||
|
||||
switch ty.(type) {
|
||||
case *entity.TypeInt, *entity.TypeWord:
|
||||
return this.blockManager.NewSub (
|
||||
irX,
|
||||
llvm.NewConstInt(irType, 1)), nil
|
||||
case *entity.TypeFloat:
|
||||
return this.blockManager.NewFSub (
|
||||
irX,
|
||||
llvm.NewConstInt(irType, 1)), nil
|
||||
}
|
||||
|
||||
case entity.OperatorModulo:
|
||||
switch ty.(type) {
|
||||
case *entity.TypeInt, *entity.TypeWord:
|
||||
if analyzer.IsUnsigned(ty) {
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewURem(x, y)
|
||||
})
|
||||
} else {
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewSRem(x, y)
|
||||
})
|
||||
}
|
||||
case *entity.TypeFloat:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewFDiv(x, y)
|
||||
})
|
||||
}
|
||||
|
||||
// logic
|
||||
case entity.OperatorLogicalNot:
|
||||
irX, err := this.generateExpression(operation.Arguments[0])
|
||||
if err != nil { return nil, err }
|
||||
return this.blockManager.NewICmp(llvm.IPredicateEQ, irX, llvm.NewConstBool(false)), nil
|
||||
|
||||
case entity.OperatorLogicalOr:
|
||||
incomings := make([]*llvm.Incoming, len(operation.Arguments) + 1)
|
||||
exit := this.blockManager.newBlock()
|
||||
|
||||
for index, argument := range operation.Arguments {
|
||||
irX, err := this.generateExpression(argument)
|
||||
if err != nil { return nil, err }
|
||||
|
||||
incomings[index] = &llvm.Incoming {
|
||||
X: llvm.NewConstBool(true),
|
||||
Predecessor: this.blockManager.Block,
|
||||
}
|
||||
|
||||
previous := this.blockManager.Block
|
||||
block := this.blockManager.newBlock()
|
||||
previous.NewCondBr(irX, exit, block)
|
||||
|
||||
}
|
||||
this.blockManager.NewBr(exit)
|
||||
incomings[len(incomings) - 1] = &llvm.Incoming {
|
||||
X: llvm.NewConstBool(false),
|
||||
Predecessor: this.blockManager.Block,
|
||||
}
|
||||
this.blockManager.Block = exit
|
||||
return this.blockManager.NewPhi(incomings...), nil
|
||||
|
||||
case entity.OperatorLogicalAnd:
|
||||
incomings := make([]*llvm.Incoming, len(operation.Arguments) + 1)
|
||||
exit := this.blockManager.newBlock()
|
||||
|
||||
for index, argument := range operation.Arguments {
|
||||
irX, err := this.generateExpression(argument)
|
||||
if err != nil { return nil, err }
|
||||
|
||||
incomings[index] = &llvm.Incoming {
|
||||
X: llvm.NewConstBool(false),
|
||||
Predecessor: this.blockManager.Block,
|
||||
}
|
||||
|
||||
previous := this.blockManager.Block
|
||||
block := this.blockManager.newBlock()
|
||||
previous.NewCondBr(irX, block, exit)
|
||||
|
||||
}
|
||||
this.blockManager.NewBr(exit)
|
||||
incomings[len(incomings) - 1] = &llvm.Incoming {
|
||||
X: llvm.NewConstBool(true),
|
||||
Predecessor: this.blockManager.Block,
|
||||
}
|
||||
this.blockManager.Block = exit
|
||||
return this.blockManager.NewPhi(incomings...), nil
|
||||
|
||||
case entity.OperatorLogicalXor:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewICmp (
|
||||
llvm.IPredicateNE,
|
||||
this.blockManager.NewICmp(llvm.IPredicateEQ, x, llvm.NewConstBool(true)),
|
||||
this.blockManager.NewICmp(llvm.IPredicateEQ, x, llvm.NewConstBool(true)))
|
||||
})
|
||||
|
||||
// bit manipulation
|
||||
case entity.OperatorNot:
|
||||
irX, err := this.generateExpression(operation.Arguments[0])
|
||||
if err != nil { return nil, err }
|
||||
return this.blockManager.NewXor (
|
||||
irX,
|
||||
llvm.NewConstInt(irType.(*llvm.TypeInt), -1)), nil
|
||||
|
||||
case entity.OperatorOr:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewOr(x, y)
|
||||
})
|
||||
|
||||
case entity.OperatorAnd:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewAnd(x, y)
|
||||
})
|
||||
|
||||
case entity.OperatorXor:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewXor(x, y)
|
||||
})
|
||||
|
||||
case entity.OperatorLeftShift:
|
||||
irX, err := this.generateExpression(operation.Arguments[0])
|
||||
if err != nil { return nil, err }
|
||||
irY, err := this.generateExpression(operation.Arguments[1])
|
||||
if err != nil { return nil, err }
|
||||
return this.blockManager.NewShl(irX, irY), nil
|
||||
|
||||
case entity.OperatorRightShift:
|
||||
irX, err := this.generateExpression(operation.Arguments[0])
|
||||
if err != nil { return nil, err }
|
||||
irY, err := this.generateExpression(operation.Arguments[1])
|
||||
if err != nil { return nil, err }
|
||||
if analyzer.IsUnsigned(ty) {
|
||||
return this.blockManager.NewLShr(irX, irY), nil
|
||||
} else {
|
||||
return this.blockManager.NewAShr(irX, irY), nil
|
||||
}
|
||||
|
||||
// comparison
|
||||
case entity.OperatorLess:
|
||||
switch ty.(type) {
|
||||
case *entity.TypeInt, *entity.TypeWord:
|
||||
var predicate llvm.IPredicate
|
||||
if analyzer.IsUnsigned(ty) {
|
||||
predicate = llvm.IPredicateULT
|
||||
} else {
|
||||
predicate = llvm.IPredicateSLT
|
||||
}
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewICmp(predicate, x, y)
|
||||
})
|
||||
case *entity.TypeFloat:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewFCmp (
|
||||
llvm.FPredicateOLT,
|
||||
x, y)
|
||||
})
|
||||
}
|
||||
|
||||
case entity.OperatorGreater:
|
||||
switch ty.(type) {
|
||||
case *entity.TypeInt, *entity.TypeWord:
|
||||
var predicate llvm.IPredicate
|
||||
if analyzer.IsUnsigned(ty) {
|
||||
predicate = llvm.IPredicateUGT
|
||||
} else {
|
||||
predicate = llvm.IPredicateSGT
|
||||
}
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewICmp(predicate, x, y)
|
||||
})
|
||||
case *entity.TypeFloat:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewFCmp (
|
||||
llvm.FPredicateOGT,
|
||||
x, y)
|
||||
})
|
||||
}
|
||||
|
||||
case entity.OperatorLessEqual:
|
||||
case entity.OperatorGreaterEqual:
|
||||
switch ty.(type) {
|
||||
case *entity.TypeInt, *entity.TypeWord:
|
||||
var predicate llvm.IPredicate
|
||||
if analyzer.IsUnsigned(ty) {
|
||||
predicate = llvm.IPredicateULE
|
||||
} else {
|
||||
predicate = llvm.IPredicateSLE
|
||||
}
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewICmp(predicate, x, y)
|
||||
})
|
||||
case *entity.TypeFloat:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewFCmp (
|
||||
llvm.FPredicateOLE,
|
||||
x, y)
|
||||
})
|
||||
}
|
||||
|
||||
case entity.OperatorGreaterEqual:
|
||||
switch ty.(type) {
|
||||
case *entity.TypeInt, *entity.TypeWord:
|
||||
var predicate llvm.IPredicate
|
||||
if analyzer.IsUnsigned(ty) {
|
||||
predicate = llvm.IPredicateUGE
|
||||
} else {
|
||||
predicate = llvm.IPredicateSGE
|
||||
}
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewICmp(predicate, x, y)
|
||||
})
|
||||
case *entity.TypeFloat:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewFCmp (
|
||||
llvm.FPredicateOGE,
|
||||
x, y)
|
||||
})
|
||||
}
|
||||
|
||||
case entity.OperatorEqual:
|
||||
switch ty.(type) {
|
||||
case *entity.TypeInt, *entity.TypeWord:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewICmp (
|
||||
llvm.IPredicateEQ,
|
||||
x, y)
|
||||
})
|
||||
case *entity.TypeFloat:
|
||||
return nSameType(func (x, y llvm.Value) llvm.Value {
|
||||
return this.blockManager.NewFCmp (
|
||||
llvm.FPredicateOEQ,
|
||||
x, y)
|
||||
})
|
||||
}
|
||||
|
||||
default:
|
||||
panic(fmt.Sprint (
|
||||
"BUG: generator doesnt know about operator ",
|
||||
"BUG: generator doesnt know about operator",
|
||||
operation.Operator))
|
||||
}
|
||||
|
||||
|
||||
panic(fmt.Sprint (
|
||||
"BUG: generator failed to generate operation",
|
||||
operation))
|
||||
}
|
||||
|
||||
func (this *generator) generateBlock (block *entity.Block) (llvm.Value, error) {
|
||||
|
|
|
@ -28,7 +28,10 @@ func testReader (test *testing.T, correct string, inputs ...io.Reader) {
|
|||
return
|
||||
}
|
||||
|
||||
module, err := NativeTarget().Generate(tree)
|
||||
module, err := (&Target {
|
||||
WordSize: 64,
|
||||
Arch: "x86_64",
|
||||
}).Generate(tree)
|
||||
if err != nil {
|
||||
test.Error("generator returned error:", err)
|
||||
return
|
||||
|
|
|
@ -1478,7 +1478,7 @@ type InstructionXor struct {
|
|||
AbstractInstructionBinary
|
||||
}
|
||||
|
||||
func (this *Block) AddXor (x, y Value) *InstructionXor {
|
||||
func (this *Block) NewXor (x, y Value) *InstructionXor {
|
||||
instruction := &InstructionXor { }
|
||||
instruction.Token = "xor"
|
||||
instruction.X = x
|
||||
|
|
Loading…
Reference in New Issue