Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alignOf, offsetOf for C based backends #5493

Closed
krux02 opened this issue Mar 6, 2017 · 6 comments
Closed

alignOf, offsetOf for C based backends #5493

krux02 opened this issue Mar 6, 2017 · 6 comments
Labels

Comments

@krux02
Copy link
Contributor

krux02 commented Mar 6, 2017

I could not find anything in the standard library, therefore I am writing it here.

http://en.cppreference.com/w/cpp/language/alignof

http://www.cplusplus.com/reference/cstddef/offsetof

https://golang.org/pkg/unsafe/#Alignof

There is a way to hack the support of offsetof into my own library with this code snippet:

template offsetof*(typ, field): expr = (var dummy: typ; cast[system.int](addr(dummy.field)) - cast[system.int](addr(dummy)))

But I think it should be in the standard library. It is also very important to have a working version of it for example when working with OpenGL, it is needed to pass an array of structs as attributes to the shader

Edit:

Unfortunately the above version is not sufficient for me anymore. I am generating shader code at compile time. I need to be able to generate blocks like the following at compile time from object type definitions:

layout(xfb_buffer = 0) out Data
{
  layout(xfb_offset = 0) vec4 val1;
  layout(xfb_offset = 16) vec3 val2;
  layout(xfb_offset = 28) float val3;
};

The above version of offsetof can only be evaluated at runtime, and therefore does not work in this context.

Edit2:

Well, what a hack, but I am impressed that it works so well (so far) for my use case.

const offsetof = """
import glm

template offsetof*(typ, field: untyped): int =
  var dummy: typ
  cast[system.int](addr(dummy.field)) - cast[system.int](addr(dummy))

"""

macro offsetsString[T](t: typedesc[T]): string =
  let tpe = t.getTypeInst[1]
  let typeImpl = tpe.getTypeImpl

  var str = offsetof

  for s in ["type ", tpe.repr, " = ", typeImpl.repr, "\n"]:
    str.add s

  for identDefs in typeImpl[2]:
    for i in 0 ..< identDefs.len - 2:
      let memberSym = identDefs[i]
      #str.add "echo \"" & $memberSym & " \", offsetof(" & $tpe & ", " & $memberSym & ")\n"
      str.add "echo offsetof(" & $tpe & ", " & $memberSym & ")\n"

  writeFile("/tmp/genoffsets.nim", str)
  let offsets = staticExec("nim c --verbosity:0 --hint[Processing]:off -r /tmp/genoffsets.nim", cache = typeImpl.lispRepr)

  result = newLit(offsets)
@Araq Araq added the Feature label Mar 23, 2017
@krux02
Copy link
Contributor Author

krux02 commented Mar 28, 2017

Well it turns out that I hate my hack a lot. I implement these features now with macros. My macro implementation will definitively have it's limitations but I think the part that I need will be possible to implement. Sad thing is, I also need to implement sizeof, because sizeof only works for primitive types at compile time. It seems like I can't statically get the size of composed types.

type
  MyType = object
    a,b: int

const
  mysize1 = sizeof(type(MyType))
  mysize2 = sizeof(type(array[0 .. 7, byte]))
  mysize3 = sizeof(type(tuple[a,b: char]))

@Araq
Copy link
Member

Araq commented Mar 29, 2017

I think you should patch the compiler.

@krux02
Copy link
Contributor Author

krux02 commented Mar 30, 2017

I implemented aligneof, sizeof and offsetof as compile time macros/templates. It does work for almost all cases correctly, except when I have an object with a packed pragma ({.packed.}). For me there is no way to detect whether an object has packed alignment or not. It would be helpful, if getTypeImpl could return an AST that contains the packed pragma, when it was there in the original type definition.

@timotheecour
Copy link
Member

timotheecour commented Aug 3, 2018

It does work for almost all cases correctly, except when I have an object with a packed pragma ({.packed.}). For me there is no way to detect whether an object has packed alignment or not. It would be helpful, if getTypeImpl could return an AST that contains the packed pragma, when it was there in the original type definition.

@krux02 would macros.hasCustomPragma help with that?

@krux02
Copy link
Contributor Author

krux02 commented Aug 4, 2018

@timotheecour Well, it really looks like I finally have to put a bit of work in this again. The implementation with macros is not really up to date anymore. There is a PR for the compiler. But think your for trying to help out. I think I really have to work on this again.

@timotheecour
Copy link
Member

@krux02 should this be closed now that @krux02 's work was merged (#5664 )?

@Araq Araq closed this as completed Oct 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants