Skip to content
This repository has been archived by the owner on May 18, 2024. It is now read-only.

Commit

Permalink
c2go fix: division by zero
Browse files Browse the repository at this point in the history
  • Loading branch information
xushiwei committed Jul 23, 2022
1 parent a392ed2 commit cf383f0
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 3 deletions.
22 changes: 19 additions & 3 deletions cl/codebuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ func isNegConst(v *gox.Element) bool {
return false
}

func isZeroConst(v *gox.Element) bool {
func isNilConst(v *gox.Element) bool {
if cval := v.CVal; cval != nil && cval.Kind() == constant.Int {
if v, ok := constant.Int64Val(cval); ok {
return v == 0
Expand All @@ -323,6 +323,13 @@ func isZeroConst(v *gox.Element) bool {
return false
}

func isZeroNumber(v *gox.Element) bool {
if cval := v.CVal; cval != nil {
return constant.Sign(cval) == 0
}
return false
}

func unaryOp(ctx *blockCtx, op token.Token, v *cast.Node) {
switch op {
case token.NOT:
Expand Down Expand Up @@ -385,6 +392,15 @@ func binaryOp(ctx *blockCtx, op token.Token, v *cast.Node) {
}
log.Panicln("binaryOp token.ADD/SUB - TODO: unexpected")
}
case token.QUO:
if isZeroNumber(arg2) && arg1.CVal != nil && isFloat(arg1.Type) {
pkg := ctx.pkg
ret := pkg.NewParam(token.NoPos, "", arg1.Type)
arg1.Val = cb.NewClosure(nil, types.NewTuple(ret), false).BodyStart(pkg).
Val(arg1).Return(1).
End().Call(0).InternalStack().Pop().Val
arg1.CVal = nil
}
}
if !isShiftOpertor(op) {
isUnt1 := isUntyped(arg1.Type)
Expand All @@ -399,8 +415,8 @@ func binaryOp(ctx *blockCtx, op token.Token, v *cast.Node) {
kind1 := checkNilComparable(arg1)
kind2 := checkNilComparable(arg2)
if kind1 != 0 || kind2 != 0 { // ptr <cmp> ptr|nil
isNil1 := isZeroConst(arg1)
isNil2 := isZeroConst(arg2)
isNil1 := isNilConst(arg1)
isNil2 := isNilConst(arg2)
if isNil1 || isNil2 { // ptr <cmp> nil
if isNil1 {
untypedZeroToNil(arg1)
Expand Down
4 changes: 4 additions & 0 deletions cl/type_and_var.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,10 @@ func isUntyped(typ types.Type) bool {
return isKind(typ, types.IsUntyped)
}

func isFloat(typ types.Type) bool {
return isKind(typ, types.IsFloat)
}

func isBool(typ types.Type) bool {
return isKind(typ, types.IsBoolean)
}
Expand Down
55 changes: 55 additions & 0 deletions testdata/forceeval/forceeval.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include <stdio.h>

/* fp_force_eval ensures that the input value is computed when that's
otherwise unused. To prevent the constant folding of the input
expression, an additional fp_barrier may be needed or a compilation
mode that does so (e.g. -frounding-math in gcc). Then it can be
used to evaluate an expression for its fenv side-effects only. */

#ifndef fp_force_evalf
#define fp_force_evalf fp_force_evalf
static inline void fp_force_evalf(float x)
{
volatile float y;
y = x;
}
#endif

#ifndef fp_force_eval
#define fp_force_eval fp_force_eval
static inline void fp_force_eval(double x)
{
volatile double y;
y = x;
}
#endif

#ifndef fp_force_evall
#define fp_force_evall fp_force_evall
static inline void fp_force_evall(long double x)
{
volatile long double y;
y = x;
}
#endif

#define FORCE_EVAL(x) do { \
if (sizeof(x) == sizeof(float)) { \
fp_force_evalf(x); \
} else if (sizeof(x) == sizeof(double)) { \
fp_force_eval(x); \
} else { \
fp_force_evall(x); \
} \
} while(0)

void f() {
FORCE_EVAL(0/0.0f);
}

volatile double x = -1;

int main() {
printf("%f, %f\n", 0/0.0, x/0.0);
return 0;
}
37 changes: 37 additions & 0 deletions testdata/forceeval/libc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package main

import (
"fmt"
"strings"
"unsafe"
)

func gostring(s *int8) string {
n, arr := 0, (*[1 << 20]byte)(unsafe.Pointer(s))
for arr[n] != 0 {
n++
}
return string(arr[:n])
}

func printf(format *int8, args ...interface{}) int32 {
goformat := gostring(format)
for i, arg := range args {
if v, ok := arg.(*int8); ok {
args[i] = gostring(v)
}
}
s := strings.ToLower(fmt.Sprintf(goformat, args...))
fmt.Print(s)
return 0
}

func __swbuf(_c int32, _p *FILE) int32 {
return _c
}

type struct___sFILEX struct{}

type struct__IO_marker struct{}
type struct__IO_codecvt struct{}
type struct__IO_wide_data struct{}

0 comments on commit cf383f0

Please sign in to comment.